diff --git a/.gn b/.gn index 0644a660..796c2d6 100644 --- a/.gn +++ b/.gn
@@ -244,6 +244,7 @@ #"//ui/*", # Just a few problems. "//url/*", "//v8/*", + "//win8/*", ] # These are the list of GN files that run exec_script. This whitelist exists
diff --git a/BUILD.gn b/BUILD.gn index 2d4e60f..f7c2c63 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -288,6 +288,7 @@ "//components/user_manager", "//components/wallpaper", "//content/shell/android:content_shell_apk", + "//content/test:video_decode_accelerator_unittest", # TODO(GYP): Are these needed, or will they be pulled in automatically? "//third_party/android_tools:android_gcm_java", @@ -603,7 +604,7 @@ } if (!is_component_build && (is_win || is_linux)) { - deps += [ "//components/mus/example:all" ] + deps += [ "//mash:all" ] } if (is_linux && !is_chromeos && !is_chromecast) {
diff --git a/DEPS b/DEPS index 691ebe0c..c6855d9 100644 --- a/DEPS +++ b/DEPS
@@ -39,15 +39,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '93c69fff535075e86596a2b224f52f454b060be3', + 'skia_revision': '0f6cca8a2070b974368652ec04b6003e9205a8a3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '2280bfa03b1173d32bd2dbad60013d8390ce2ec5', + 'v8_revision': '0164a63f9261df5c20882f9379cd351272a2e746', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. - 'swarming_revision': '05e17879accce360bee999cd9ec891d761056bc2', + 'swarming_revision': 'df99a00d96fae932bae824dccba13156bf7eddd0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -59,7 +59,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '8840ec9b5c54da9dc9aae3afb8585a2ff80758d9', + 'pdfium_revision': '36476923ae5eb8e9283e605f3c85ee8811c86014', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS index 51ea770..594b701 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -185,6 +185,16 @@ '|chrome/test/data/extensions/api_test/cast_'\ '|content/public/renderer/media_stream_', }, + 'certificate_transparency': { + 'filepath': 'components/certificate_transparency/'\ + '|components/packed_ct_ev_whitelist/'\ + '|net/cert/ct_'\ + '|net/cert/multi_log_ct_verifier'\ + '|net/cert/sct_status_flags.h'\ + '|net/cert/signed_certificate_timestamp'\ + '|net/cert/signed_tree_head'\ + '|net/test/ct_', + }, 'chromecast': { 'filepath': 'chromecast/', }, @@ -1278,6 +1288,7 @@ 'miu+watch@chromium.org', 'xjz+watch@chromium.org'], 'cc': ['cc-bugs@chromium.org'], + 'certificate_transparency': ['eranm@chromium.org', 'certificate-transparency-chrome@googlegroups.com'], 'chrome_elf': ['caitkp+watch@chromium.org',], 'chrome_views': ['tfarina@chromium.org'], 'chromecast': ['gunsch+watch@chromium.org',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 2c243784..0b88116 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -356,8 +356,7 @@ } void AwContentBrowserClient::AllowCertificateError( - int render_process_id, - int render_frame_id, + content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, @@ -368,7 +367,7 @@ const base::Callback<void(bool)>& callback, content::CertificateRequestResultType* result) { AwContentsClientBridgeBase* client = - AwContentsClientBridgeBase::FromID(render_process_id, render_frame_id); + AwContentsClientBridgeBase::FromWebContents(web_contents); bool cancel_request = true; if (client) client->AllowCertificateError(cert_error,
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h index a3a814e..960c3e88 100644 --- a/android_webview/browser/aw_content_browser_client.h +++ b/android_webview/browser/aw_content_browser_client.h
@@ -91,8 +91,7 @@ const std::vector<std::pair<int, int>>& render_frames) override; content::QuotaPermissionContext* CreateQuotaPermissionContext() override; void AllowCertificateError( - int render_process_id, - int render_frame_id, + content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url,
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc index c61f2e1..fa9ea17 100644 --- a/android_webview/browser/browser_view_renderer.cc +++ b/android_webview/browser/browser_view_renderer.cc
@@ -30,6 +30,8 @@ const double kEpsilon = 1e-8; +const int64 kFallbackTickTimeoutInMilliseconds = 100; + // Used to calculate memory allocation. Determined experimentally. const size_t kMemoryMultiplier = 20; const size_t kBytesPerPixel = 4; @@ -101,7 +103,8 @@ max_page_scale_factor_(0.f), on_new_picture_enable_(false), clear_view_(false), - offscreen_pre_raster_(false) {} + offscreen_pre_raster_(false), + fallback_tick_pending_(false) {} BrowserViewRenderer::~BrowserViewRenderer() { } @@ -222,6 +225,12 @@ shared_renderer_state_.SetScrollOffsetOnUI(last_on_draw_scroll_offset_); hardware_enabled_ = true; + return CompositeHw(); +} + +bool BrowserViewRenderer::CompositeHw() { + CancelFallbackTick(); + ReturnResourceFromParent(); UpdateMemoryPolicy(); @@ -261,16 +270,14 @@ transform_for_tile_priority, offscreen_pre_raster_, parent_draw_constraints.is_layer)); - // If we haven't received a kModeSync functor call since the last - // CompositeHw then we need to discard the resources that are being - // held onto by the previously prepared frame. + // Uncommitted frame can happen with consecutive fallback ticks. ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI()); shared_renderer_state_.SetCompositorFrameOnUI(child_frame.Pass()); return true; } void BrowserViewRenderer::UpdateParentDrawConstraints() { - PostInvalidate(); + PostInvalidateWithFallback(); ParentCompositorDrawConstraints parent_draw_constraints = shared_renderer_state_.GetParentDrawConstraintsOnUI(); client_->ParentDrawConstraintsUpdated(parent_draw_constraints); @@ -344,7 +351,7 @@ clear_view_ = true; // Always invalidate ignoring the compositor to actually clear the webview. - PostInvalidate(); + PostInvalidateWithFallback(); } void BrowserViewRenderer::SetOffscreenPreRaster(bool enable) { @@ -642,11 +649,80 @@ void BrowserViewRenderer::PostInvalidate() { TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate", TRACE_EVENT_SCOPE_THREAD); + PostInvalidateWithFallback(); +} + +void BrowserViewRenderer::PostInvalidateWithFallback() { + // Always call view invalidate. We rely the Android framework to ignore the + // invalidate when it's not needed such as when view is not visible. client_->PostInvalidate(); + + // Stop fallback ticks when one of these is true. + // 1) Webview is paused. Also need to check we are not in clear view since + // paused, offscreen still expect clear view to recover. + // 2) If we are attached to window and the window is not visible (eg when + // app is in the background). We are sure in this case the webview is used + // "on-screen" but that updates are not needed when in the background. + bool throttle_fallback_tick = + (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_); + + if (throttle_fallback_tick || fallback_tick_pending_) + return; + + DCHECK(post_fallback_tick_.IsCancelled()); + DCHECK(fallback_tick_fired_.IsCancelled()); + + post_fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick, + base::Unretained(this))); + ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback()); + fallback_tick_pending_ = true; +} + +void BrowserViewRenderer::CancelFallbackTick() { + post_fallback_tick_.Cancel(); + fallback_tick_fired_.Cancel(); + fallback_tick_pending_ = false; +} + +void BrowserViewRenderer::PostFallbackTick() { + DCHECK(fallback_tick_fired_.IsCancelled()); + TRACE_EVENT0("android_webview", "BrowserViewRenderer::PostFallbackTick"); + post_fallback_tick_.Cancel(); + fallback_tick_fired_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired, + base::Unretained(this))); + ui_task_runner_->PostDelayedTask( + FROM_HERE, fallback_tick_fired_.callback(), + base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds)); +} + +void BrowserViewRenderer::FallbackTickFired() { + TRACE_EVENT0("android_webview", "BrowserViewRenderer::FallbackTickFired"); + // This should only be called if OnDraw or DrawGL did not come in time, which + // means fallback_tick_pending_ must still be true. + DCHECK(fallback_tick_pending_); + fallback_tick_fired_.Cancel(); + fallback_tick_pending_ = false; + if (compositor_) { + if (hardware_enabled_ && !size_.IsEmpty()) { + CompositeHw(); + } else { + ForceFakeCompositeSW(); + } + } +} + +void BrowserViewRenderer::ForceFakeCompositeSW() { + DCHECK(compositor_); + SkBitmap bitmap; + bitmap.allocN32Pixels(1, 1); + bitmap.eraseColor(0); + SkCanvas canvas(bitmap); + CompositeSW(&canvas); } bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) { DCHECK(compositor_); + CancelFallbackTick(); ReturnResourceFromParent(); return compositor_->DemandDrawSw(canvas); } @@ -668,6 +744,8 @@ base::StringAppendF(&str, "window_visible: %d ", window_visible_); base::StringAppendF(&str, "dip_scale: %f ", dip_scale_); base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_); + base::StringAppendF(&str, "fallback_tick_pending: %d ", + fallback_tick_pending_); base::StringAppendF(&str, "view size: %s ", size_.ToString().c_str()); base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); base::StringAppendF(&str,
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h index 4d31689..21c28c8 100644 --- a/android_webview/browser/browser_view_renderer.h +++ b/android_webview/browser/browser_view_renderer.h
@@ -120,12 +120,18 @@ private: void SetTotalRootLayerScrollOffset(const gfx::Vector2dF& new_value_dip); bool CanOnDraw(); + // Posts an invalidate with fallback tick. All invalidates posted while an + // invalidate is pending will be posted as a single invalidate after the + // pending invalidate is done. + void PostInvalidateWithFallback(); + void CancelFallbackTick(); void UpdateCompositorIsActive(); bool CompositeSW(SkCanvas* canvas); scoped_refptr<base::trace_event::ConvertableToTraceFormat> RootLayerStateAsValue(const gfx::Vector2dF& total_scroll_offset_dip, const gfx::SizeF& scrollable_size_dip); + bool CompositeHw(); void ReturnUnusedResource(scoped_ptr<ChildFrame> frame); void ReturnResourceFromParent(); @@ -136,6 +142,11 @@ void PostFallbackTick(); void FallbackTickFired(); + // Force invoke the compositor to run produce a 1x1 software frame that is + // immediately discarded. This is a hack to force invoke parts of the + // compositor that are not directly exposed here. + void ForceFakeCompositeSW(); + gfx::Vector2d max_scroll_offset() const; void UpdateMemoryPolicy(); @@ -168,6 +179,10 @@ gfx::Vector2d last_on_draw_scroll_offset_; gfx::Rect last_on_draw_global_visible_rect_; + base::CancelableClosure post_fallback_tick_; + base::CancelableClosure fallback_tick_fired_; + bool fallback_tick_pending_; + gfx::Size size_; gfx::SizeF scrollable_size_dip_;
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.cc b/android_webview/browser/net/android_stream_reader_url_request_job.cc index 173bdbb..dc288faa5 100644 --- a/android_webview/browser/net/android_stream_reader_url_request_job.cc +++ b/android_webview/browser/net/android_stream_reader_url_request_job.cc
@@ -21,7 +21,6 @@ #include "content/public/browser/browser_thread.h" #include "net/base/io_buffer.h" #include "net/base/mime_util.h" -#include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" @@ -90,6 +89,7 @@ net::NetworkDelegate* network_delegate, scoped_ptr<Delegate> delegate) : URLRequestJob(request, network_delegate), + range_parse_result_(net::OK), delegate_(delegate.Pass()), weak_factory_(this) { DCHECK(delegate_); @@ -101,6 +101,7 @@ scoped_ptr<DelegateObtainer> delegate_obtainer, bool) : URLRequestJob(request, network_delegate), + range_parse_result_(net::OK), delegate_obtainer_(delegate_obtainer.Pass()), weak_factory_(this) { DCHECK(delegate_obtainer_); @@ -141,7 +142,10 @@ base::Bind(&AndroidStreamReaderURLRequestJob::DelegateObtained, weak_factory_.GetWeakPtr())); } else { - DoStart(); + // Run DoStart asynchronously to avoid re-entering the delegate. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&AndroidStreamReaderURLRequestJob::DoStart, + weak_factory_.GetWeakPtr())); } } @@ -202,45 +206,29 @@ set_expected_content_size(result); HeadersComplete(kHTTPOk, kHTTPOkText); } else { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + NotifyStartError( + net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); } } void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) { DCHECK(thread_checker_.CalledOnValidThread()); - // The URLRequest API contract requires that: - // * NotifyDone be called once, to set the status code, indicate the job is - // finished (there will be no further IO), - // * NotifyReadComplete be called if false is returned from ReadRawData to - // indicate that the IOBuffer will not be used by the job anymore. - // There might be multiple calls to ReadRawData (and thus multiple calls to - // NotifyReadComplete), which is why NotifyDone is called only on errors - // (result < 0) and end of data (result == 0). - if (result == 0) { - NotifyDone(net::URLRequestStatus()); - } else if (result < 0) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); - } else { - // Clear the IO_PENDING status. - SetStatus(net::URLRequestStatus()); - } - NotifyReadComplete(result); + + ReadRawDataComplete(result); } base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); } -bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, - int dest_size, - int* bytes_read) { +int AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, + int dest_size) { DCHECK(thread_checker_.CalledOnValidThread()); if (!input_stream_reader_wrapper_.get()) { // This will happen if opening the InputStream fails in which case the // error is communicated by setting the HTTP response status header rather // than failing the request during the header fetch phase. - *bytes_read = 0; - return true; + return 0; } PostTaskAndReplyWithResult( @@ -251,9 +239,7 @@ base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, weak_factory_.GetWeakPtr())); - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, - net::ERR_IO_PENDING)); - return false; + return net::ERR_IO_PENDING; } bool AndroidStreamReaderURLRequestJob::GetMimeType( @@ -303,6 +289,11 @@ void AndroidStreamReaderURLRequestJob::DoStart() { DCHECK(thread_checker_.CalledOnValidThread()); + if (range_parse_result_ != net::OK) { + NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, + range_parse_result_)); + return; + } // Start reading asynchronously so that all error reporting and data // callbacks happen as they would for network requests. SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, @@ -383,19 +374,18 @@ const net::HttpRequestHeaders& headers) { std::string range_header; if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { - // We only extract the "Range" header so that we know how many bytes in the - // stream to skip and how many to read after that. + // This job only cares about the Range header so that we know how many bytes + // in the stream to skip and how many to read after that. Note that + // validation is deferred to DoStart(), because NotifyStartError() is not + // legal to call since the job has not started. std::vector<net::HttpByteRange> ranges; if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { - if (ranges.size() == 1) { + if (ranges.size() == 1) byte_range_ = ranges[0]; - } else { - // We don't support multiple range requests in one single URL request, - // because we need to do multipart encoding here. - NotifyDone( - net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); - } + } else { + // We don't support multiple range requests in one single URL request, + // because we need to do multipart encoding here. + range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; } } }
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.h b/android_webview/browser/net/android_stream_reader_url_request_job.h index e21d7655..645be13 100644 --- a/android_webview/browser/net/android_stream_reader_url_request_job.h +++ b/android_webview/browser/net/android_stream_reader_url_request_job.h
@@ -15,6 +15,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" +#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request_job.h" @@ -96,7 +97,7 @@ // URLRequestJob: void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; bool GetMimeType(std::string* mime_type) const override; bool GetCharset(std::string* charset) override; @@ -131,6 +132,7 @@ void OnReaderReadCompleted(int bytes_read); net::HttpByteRange byte_range_; + net::Error range_parse_result_; scoped_ptr<net::HttpResponseInfo> response_info_; scoped_ptr<Delegate> delegate_; scoped_ptr<DelegateObtainer> delegate_obtainer_;
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java index 932b3c6..0ca81ae 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -39,6 +39,7 @@ import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.R; import org.chromium.base.CommandLine; +import org.chromium.base.ContextUtils; import org.chromium.base.MemoryPressureListener; import org.chromium.base.PathService; import org.chromium.base.PathUtils; @@ -48,7 +49,6 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.library_loader.ProcessInitException; -import org.chromium.content.app.ContentMain; import org.chromium.content.browser.ContentViewStatics; import org.chromium.ui.base.ResourceBundle; @@ -423,7 +423,7 @@ // will bring up just the parts it needs to make this work on a temporary // basis until Chromium is started for real. The temporary cookie manager // needs the application context to have been set. - ContentMain.initApplicationContext(getWrappedCurrentApplicationContext()); + ContextUtils.initApplicationContext(getWrappedCurrentApplicationContext()); } mCookieManager = new CookieManagerAdapter(new AwCookieManager()); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java index 6e67ed1..6505102 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java
@@ -14,8 +14,8 @@ import org.chromium.android_webview.AwWebResourceResponse; import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.CookieUtils; +import org.chromium.base.ContextUtils; import org.chromium.base.test.util.Feature; -import org.chromium.content.app.ContentMain; import org.chromium.net.test.util.TestWebServer; @@ -30,7 +30,7 @@ @Override protected void setUp() throws Exception { super.setUp(); - ContentMain.initApplicationContext(getActivity().getApplicationContext()); + ContextUtils.initApplicationContext(getActivity().getApplicationContext()); } @Override
diff --git a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/TelemetryActivity.java b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/TelemetryActivity.java index fc50f249..e2a34f93 100644 --- a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/TelemetryActivity.java +++ b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/TelemetryActivity.java
@@ -28,6 +28,9 @@ CookieManager.setAcceptFileSchemeCookies(true); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); + settings.setUseWideViewPort(true); + settings.setLoadWithOverviewMode(true); + settings.setDomStorageEnabled(true); Intent intent = getIntent(); String userAgentString = intent.getStringExtra("userAgent");
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 862e57c..c2a0611 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -27,6 +27,7 @@ "//base/third_party/dynamic_annotations", "//cc", "//components/device_event_log", + "//components/onc", "//components/signin/core/account_id", "//components/user_manager", "//components/wallpaper",
diff --git a/ash/ash.gyp b/ash/ash.gyp index bf78086..6686402 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp
@@ -945,6 +945,7 @@ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../cc/cc.gyp:cc', '../components/components.gyp:device_event_log_component', + '../components/components.gyp:onc_component', '../components/components.gyp:signin_core_account_id', '../components/components.gyp:user_manager', '../components/components.gyp:wallpaper',
diff --git a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc index f5df053..de926faba 100644 --- a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc +++ b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
@@ -616,7 +616,7 @@ EXPECT_TRUE(RotationLocked()); } -// Verifies rotating an inactive Display is sucessful. +// Verifies rotating an inactive Display is successful. TEST_F(ScreenOrientationControllerTest, RotateInactiveDisplay) { const int64 kInternalDisplayId = 9; const int64 kExternalDisplayId = 10;
diff --git a/ash/system/chromeos/network/network_state_list_detailed_view.cc b/ash/system/chromeos/network/network_state_list_detailed_view.cc index f806dcd8..ea37786 100644 --- a/ash/system/chromeos/network/network_state_list_detailed_view.cc +++ b/ash/system/chromeos/network/network_state_list_detailed_view.cc
@@ -31,7 +31,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/login/login_state.h" #include "chromeos/network/device_state.h" +#include "chromeos/network/managed_network_configuration_handler.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "grit/ash_resources.h" @@ -59,6 +61,7 @@ #include "ui/views/widget/widget.h" using chromeos::DeviceState; +using chromeos::LoginState; using chromeos::NetworkHandler; using chromeos::NetworkState; using chromeos::NetworkStateHandler; @@ -93,6 +96,23 @@ return view; } +bool PolicyProhibitsUnmanaged() { + if (!LoginState::IsInitialized() || !LoginState::Get()->IsUserLoggedIn()) + return false; + bool policy_prohibites_unmanaged = false; + const base::DictionaryValue* global_network_config = + NetworkHandler::Get() + ->managed_network_configuration_handler() + ->GetGlobalConfigFromPolicy( + std::string() /* no username hash, device policy */); + if (global_network_config) { + global_network_config->GetBooleanWithoutPathExpansion( + ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect, + &policy_prohibites_unmanaged); + } + return policy_prohibites_unmanaged; +} + } // namespace //------------------------------------------------------------------------------ @@ -459,6 +479,11 @@ other_wifi_ = new TrayPopupLabelButton( this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_WIFI)); bottom_row->AddChildView(other_wifi_); + if (PolicyProhibitsUnmanaged()) { + other_wifi_->SetEnabled(false); + other_wifi_->SetTooltipText(l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED_OTHER)); + } turn_on_wifi_ = new TrayPopupLabelButton( this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_TURN_ON_WIFI)); @@ -785,6 +810,7 @@ view->SetBorder( views::Border::CreateEmptyBorder(0, kTrayPopupPaddingHorizontal, 0, 0)); views::View* controlled_icon = CreateControlledByExtensionView(info); + view->set_tooltip(info.tooltip); if (controlled_icon) view->AddChildView(controlled_icon); return view; @@ -805,6 +831,7 @@ HoverHighlightView* highlight = static_cast<HoverHighlightView*>(view); highlight->AddIconAndLabel(info.image, info.label, info.highlight); views::View* controlled_icon = CreateControlledByExtensionView(info); + highlight->set_tooltip(info.tooltip); if (controlled_icon) view->AddChildView(controlled_icon); }
diff --git a/ash/system/tray/hover_highlight_view.cc b/ash/system/tray/hover_highlight_view.cc index 164cb41e..ee43e71 100644 --- a/ash/system/tray/hover_highlight_view.cc +++ b/ash/system/tray/hover_highlight_view.cc
@@ -50,6 +50,14 @@ HoverHighlightView::~HoverHighlightView() { } +bool HoverHighlightView::GetTooltipText(const gfx::Point& p, + base::string16* tooltip) const { + if (tooltip_.empty()) + return false; + *tooltip = tooltip_; + return true; +} + void HoverHighlightView::AddIconAndLabel(const gfx::ImageSkia& image, const base::string16& text, bool highlight) {
diff --git a/ash/system/tray/hover_highlight_view.h b/ash/system/tray/hover_highlight_view.h index 6b9d1a22..40819bd 100644 --- a/ash/system/tray/hover_highlight_view.h +++ b/ash/system/tray/hover_highlight_view.h
@@ -26,6 +26,10 @@ explicit HoverHighlightView(ViewClickListener* listener); ~HoverHighlightView() override; + // views::View + bool GetTooltipText(const gfx::Point& p, + base::string16* tooltip) const override; + // Convenience function for adding an icon and a label. This also sets the // accessible name. void AddIconAndLabel(const gfx::ImageSkia& image, @@ -66,6 +70,8 @@ bool hover() const { return hover_; } + void set_tooltip(const base::string16& tooltip) { tooltip_ = tooltip; } + protected: // Overridden from views::View. void GetAccessibleState(ui::AXViewState* state) override; @@ -103,6 +109,7 @@ bool expandable_; bool checkable_; bool checked_; + base::string16 tooltip_; DISALLOW_COPY_AND_ASSIGN(HoverHighlightView); };
diff --git a/base/BUILD.gn b/base/BUILD.gn index aabfe67..e9bc061 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -102,6 +102,8 @@ "android/command_line_android.h", "android/content_uri_utils.cc", "android/content_uri_utils.h", + "android/context_utils.cc", + "android/context_utils.h", "android/cpu_features.cc", "android/cxa_demangle_stub.cc", "android/event_log.cc", @@ -1613,6 +1615,7 @@ "android/java/src/org/chromium/base/BuildInfo.java", "android/java/src/org/chromium/base/CommandLine.java", "android/java/src/org/chromium/base/ContentUriUtils.java", + "android/java/src/org/chromium/base/ContextUtils.java", "android/java/src/org/chromium/base/CpuFeatures.java", "android/java/src/org/chromium/base/EventLog.java", "android/java/src/org/chromium/base/FieldTrialList.java",
diff --git a/base/allocator/allocator_extension.cc b/base/allocator/allocator_extension.cc index bcfe89b..75918d1c 100644 --- a/base/allocator/allocator_extension.cc +++ b/base/allocator/allocator_extension.cc
@@ -9,22 +9,6 @@ namespace base { namespace allocator { -bool GetAllocatorWasteSize(size_t* size) { - thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function = - thunks::GetGetAllocatorWasteSizeFunction(); - return get_allocator_waste_size_function != NULL && - get_allocator_waste_size_function(size); -} - -void GetStats(char* buffer, int buffer_length) { - DCHECK_GT(buffer_length, 0); - thunks::GetStatsFunction get_stats_function = thunks::GetGetStatsFunction(); - if (get_stats_function) - get_stats_function(buffer, buffer_length); - else - buffer[0] = '\0'; -} - void ReleaseFreeMemory() { thunks::ReleaseFreeMemoryFunction release_free_memory_function = thunks::GetReleaseFreeMemoryFunction(); @@ -32,19 +16,6 @@ release_free_memory_function(); } -void SetGetAllocatorWasteSizeFunction( - thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function) { - DCHECK_EQ(thunks::GetGetAllocatorWasteSizeFunction(), - reinterpret_cast<thunks::GetAllocatorWasteSizeFunction>(NULL)); - thunks::SetGetAllocatorWasteSizeFunction(get_allocator_waste_size_function); -} - -void SetGetStatsFunction(thunks::GetStatsFunction get_stats_function) { - DCHECK_EQ(thunks::GetGetStatsFunction(), - reinterpret_cast<thunks::GetStatsFunction>(NULL)); - thunks::SetGetStatsFunction(get_stats_function); -} - void SetReleaseFreeMemoryFunction( thunks::ReleaseFreeMemoryFunction release_free_memory_function) { DCHECK_EQ(thunks::GetReleaseFreeMemoryFunction(),
diff --git a/base/allocator/allocator_extension.h b/base/allocator/allocator_extension.h index c8061633..e2f1e70 100644 --- a/base/allocator/allocator_extension.h +++ b/base/allocator/allocator_extension.h
@@ -14,28 +14,10 @@ namespace base { namespace allocator { -// Request the allocator to report value of its waste memory size. -// Waste size corresponds to memory that has been allocated from the OS but -// not passed up to the application. It e.g. includes memory retained by free -// lists, internal data, chunks padding, etc. -// -// |size| pointer to the returned value, must be not NULL. -// Returns true if the value has been returned, false otherwise. -BASE_EXPORT bool GetAllocatorWasteSize(size_t* size); - -// Request that the allocator print a human-readable description of the current -// state of the allocator into a null-terminated string in the memory segment -// buffer[0,buffer_length-1]. -// -// |buffer| must point to a valid piece of memory -// |buffer_length| must be > 0. -BASE_EXPORT void GetStats(char* buffer, int buffer_length); - // Request that the allocator release any free memory it knows about to the // system. BASE_EXPORT void ReleaseFreeMemory(); - // These settings allow specifying a callback used to implement the allocator // extension functions. These are optional, but if set they must only be set // once. These will typically called in an allocator-specific initialization @@ -44,11 +26,6 @@ // No threading promises are made. The caller is responsible for making sure // these pointers are set before any other threads attempt to call the above // functions. -BASE_EXPORT void SetGetAllocatorWasteSizeFunction( - thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function); - -BASE_EXPORT void SetGetStatsFunction( - thunks::GetStatsFunction get_stats_function); BASE_EXPORT void SetReleaseFreeMemoryFunction( thunks::ReleaseFreeMemoryFunction release_free_memory_function);
diff --git a/base/allocator/allocator_extension_thunks.cc b/base/allocator/allocator_extension_thunks.cc index 8d0358db..8dedb986c 100644 --- a/base/allocator/allocator_extension_thunks.cc +++ b/base/allocator/allocator_extension_thunks.cc
@@ -17,28 +17,9 @@ // can depend on it. This file can't depend on anything else in base, including // logging. -static GetAllocatorWasteSizeFunction g_get_allocator_waste_size_function = NULL; -static GetStatsFunction g_get_stats_function = NULL; static ReleaseFreeMemoryFunction g_release_free_memory_function = NULL; static GetNumericPropertyFunction g_get_numeric_property_function = NULL; -void SetGetAllocatorWasteSizeFunction( - GetAllocatorWasteSizeFunction get_allocator_waste_size_function) { - g_get_allocator_waste_size_function = get_allocator_waste_size_function; -} - -GetAllocatorWasteSizeFunction GetGetAllocatorWasteSizeFunction() { - return g_get_allocator_waste_size_function; -} - -void SetGetStatsFunction(GetStatsFunction get_stats_function) { - g_get_stats_function = get_stats_function; -} - -GetStatsFunction GetGetStatsFunction() { - return g_get_stats_function; -} - void SetReleaseFreeMemoryFunction( ReleaseFreeMemoryFunction release_free_memory_function) { g_release_free_memory_function = release_free_memory_function;
diff --git a/base/allocator/allocator_extension_thunks.h b/base/allocator/allocator_extension_thunks.h index f1b4a93..c316767 100644 --- a/base/allocator/allocator_extension_thunks.h +++ b/base/allocator/allocator_extension_thunks.h
@@ -15,15 +15,6 @@ // new allocator extension from a specific allocator implementation to base. // See allocator_extension.h to see the interface that base exports. -typedef bool (*GetAllocatorWasteSizeFunction)(size_t* size); -void SetGetAllocatorWasteSizeFunction( - GetAllocatorWasteSizeFunction get_allocator_waste_size_function); -GetAllocatorWasteSizeFunction GetGetAllocatorWasteSizeFunction(); - -typedef void (*GetStatsFunction)(char* buffer, int buffer_length); -void SetGetStatsFunction(GetStatsFunction get_stats_function); -GetStatsFunction GetGetStatsFunction(); - typedef void (*ReleaseFreeMemoryFunction)(); void SetReleaseFreeMemoryFunction( ReleaseFreeMemoryFunction release_free_memory_function);
diff --git a/base/android/application_status_listener.cc b/base/android/application_status_listener.cc index a139268..5aee781 100644 --- a/base/android/application_status_listener.cc +++ b/base/android/application_status_listener.cc
@@ -65,12 +65,6 @@ state); } -// static -ApplicationState ApplicationStatusListener::GetState() { - return static_cast<ApplicationState>( - Java_ApplicationStatus_getStateForApplication(AttachCurrentThread())); -} - static void OnApplicationStateChange(JNIEnv* env, const JavaParamRef<jclass>& clazz, jint new_state) {
diff --git a/base/android/application_status_listener.h b/base/android/application_status_listener.h index 866ec8b..30048b2 100644 --- a/base/android/application_status_listener.h +++ b/base/android/application_status_listener.h
@@ -27,7 +27,6 @@ // A Java counterpart will be generated for this enum. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base enum ApplicationState { - APPLICATION_STATE_UNKNOWN = 0, APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = 1, APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = 2, APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = 3, @@ -74,9 +73,6 @@ // Internal use only: must be public to be called from JNI and unit tests. static void NotifyApplicationStateChange(ApplicationState state); - // Expose jni call for ApplicationStatus.getStateForApplication. - static ApplicationState GetState(); - private: void Notify(ApplicationState state);
diff --git a/base/android/base_jni_registrar.cc b/base/android/base_jni_registrar.cc index 752dcff..9ca3ce1 100644 --- a/base/android/base_jni_registrar.cc +++ b/base/android/base_jni_registrar.cc
@@ -10,6 +10,7 @@ #include "base/android/build_info.h" #include "base/android/command_line_android.h" #include "base/android/content_uri_utils.h" +#include "base/android/context_utils.h" #include "base/android/cpu_features.h" #include "base/android/event_log.h" #include "base/android/field_trial_list.h" @@ -39,13 +40,13 @@ static RegistrationMethod kBaseRegisteredMethods[] = { {"AnimationFrameTimeHistogram", base::android::RegisterAnimationFrameTimeHistogram}, - {"ApkAssets", - base::android::RegisterApkAssets}, + {"ApkAssets", base::android::RegisterApkAssets}, {"ApplicationStatusListener", base::android::ApplicationStatusListener::RegisterBindings}, {"BuildInfo", base::android::BuildInfo::RegisterBindings}, {"CommandLine", base::android::RegisterCommandLine}, {"ContentUriUtils", base::RegisterContentUriUtils}, + {"ContextUtils", base::android::RegisterContextUtils}, {"CpuFeatures", base::android::RegisterCpuFeatures}, {"EventLog", base::android::RegisterEventLog}, {"FieldTrialList", base::android::RegisterFieldTrialList},
diff --git a/base/android/context_utils.cc b/base/android/context_utils.cc new file mode 100644 index 0000000..5e10f21 --- /dev/null +++ b/base/android/context_utils.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/android/context_utils.h" + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" +#include "base/lazy_instance.h" +#include "jni/ContextUtils_jni.h" + +using base::android::JavaRef; + +namespace base { +namespace android { + +namespace { + +// Leak the global app context, as it is used from a non-joinable worker thread +// that may still be running at shutdown. There is no harm in doing this. +base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject>>::Leaky + g_application_context = LAZY_INSTANCE_INITIALIZER; + +void SetNativeApplicationContext(JNIEnv* env, const JavaRef<jobject>& context) { + if (env->IsSameObject(g_application_context.Get().obj(), context.obj())) { + // It's safe to set the context more than once if it's the same context. + return; + } + DCHECK(g_application_context.Get().is_null()); + g_application_context.Get().Reset(context); +} + +} // namespace + +const jobject GetApplicationContext() { + DCHECK(!g_application_context.Get().is_null()); + return g_application_context.Get().obj(); +} + +void InitApplicationContext(JNIEnv* env, const JavaRef<jobject>& context) { + SetNativeApplicationContext(env, context); + Java_ContextUtils_initJavaSideApplicationContext(env, context.obj()); +} + +static void InitNativeSideApplicationContext( + JNIEnv* env, + const JavaParamRef<jclass>& clazz, + const JavaParamRef<jobject>& context) { + SetNativeApplicationContext(env, context); +} + +bool RegisterContextUtils(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace android +} // namespace base
diff --git a/base/android/context_utils.h b/base/android/context_utils.h new file mode 100644 index 0000000..67e6335 --- /dev/null +++ b/base/android/context_utils.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 BASE_ANDROID_CONTEXT_UTILS_H_ +#define BASE_ANDROID_CONTEXT_UTILS_H_ + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" +#include "base/base_export.h" + +namespace base { +namespace android { + +// Gets a global ref to the application context set with +// InitApplicationContext(). Ownership is retained by the function - the caller +// must NOT release it. +const BASE_EXPORT jobject GetApplicationContext(); + +// Initialize the global application context object. +// Either this or the Java equivalent ContextUtils.initApplicationContext must +// be called once during startup. JNI bindings must have been initialized, as +// the context is stored on both sides. +BASE_EXPORT void InitApplicationContext( + JNIEnv* env, + const base::android::JavaRef<jobject>& context); + +bool RegisterContextUtils(JNIEnv* env); + +} // namespace android +} // namespace base + +#endif // BASE_ANDROID_CONTEXT_UTILS_H_
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java index 50e1b28..9f77595 100644 --- a/base/android/java/src/org/chromium/base/ApplicationStatus.java +++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -309,7 +309,6 @@ /** * @return The state of the application (see {@link ApplicationState}). */ - @CalledByNative public static int getStateForApplication() { synchronized (sCachedApplicationStateLock) { if (sCachedApplicationState == null) {
diff --git a/base/android/java/src/org/chromium/base/ContentUriUtils.java b/base/android/java/src/org/chromium/base/ContentUriUtils.java index 6b5542a68..528af8f 100644 --- a/base/android/java/src/org/chromium/base/ContentUriUtils.java +++ b/base/android/java/src/org/chromium/base/ContentUriUtils.java
@@ -57,7 +57,7 @@ * * @param context {@link Context} in interest * @param uriString the content URI to open - * @return file desciptor upon sucess, or -1 otherwise. + * @return file desciptor upon success, or -1 otherwise. */ @CalledByNative public static int openContentUriForRead(Context context, String uriString) {
diff --git a/base/android/java/src/org/chromium/base/ContextUtils.java b/base/android/java/src/org/chromium/base/ContextUtils.java new file mode 100644 index 0000000..51adcff --- /dev/null +++ b/base/android/java/src/org/chromium/base/ContextUtils.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.base; + +import android.content.Context; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * This class provides Android Context utility methods. + */ +@JNINamespace("base::android") +public class ContextUtils { + private static Context sApplicationContext; + + /** + * Get the Android application context. + * + * Under normal circumstances there is only one application context in a process, so it's safe + * to treat this as a global. In WebView it's possible for more than one app using WebView to be + * running in a single process, but this mechanism is rarely used and this is not the only + * problem in that scenario, so we don't currently forbid using it as a global. + * + * Do not downcast the context returned by this method to Application (or any subclass). It may + * not be an Application object; it may be wrapped in a ContextWrapper. The only assumption you + * may make is that it is a Context whose lifetime is the same as the lifetime of the process. + */ + public static Context getApplicationContext() { + assert sApplicationContext != null; + return sApplicationContext; + } + + /** + * Initialize the Android application context. + * + * Either this or the native equivalent base::android::InitApplicationContext must be called + * once during startup. JNI bindings must have been initialized, as the context is stored on + * both sides. + */ + public static void initApplicationContext(Context appContext) { + assert appContext != null; + assert sApplicationContext == null || sApplicationContext == appContext; + initJavaSideApplicationContext(appContext); + nativeInitNativeSideApplicationContext(appContext); + } + + /** + * JUnit Robolectric tests run without native code; allow them to set just the Java-side + * context. Do not use in configurations that actually run on Android! + */ + public static void initApplicationContextForJUnitTests(Context appContext) { + initJavaSideApplicationContext(appContext); + } + + @CalledByNative + private static void initJavaSideApplicationContext(Context appContext) { + sApplicationContext = appContext; + } + + private static native void nativeInitNativeSideApplicationContext(Context appContext); +}
diff --git a/base/android/jni_android.cc b/base/android/jni_android.cc index 3db0fc8..26a266df 100644 --- a/base/android/jni_android.cc +++ b/base/android/jni_android.cc
@@ -20,10 +20,6 @@ bool g_disable_manual_jni_registration = false; JavaVM* g_jvm = NULL; -// Leak the global app context, as it is used from a non-joinable worker thread -// that may still be running at shutdown. There is no harm in doing this. -base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky - g_application_context = LAZY_INSTANCE_INITIALIZER; base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky g_class_loader = LAZY_INSTANCE_INITIALIZER; jmethodID g_class_loader_load_class_method_id = 0; @@ -78,15 +74,6 @@ return g_jvm != NULL; } -void InitApplicationContext(JNIEnv* env, const JavaRef<jobject>& context) { - if (env->IsSameObject(g_application_context.Get().obj(), context.obj())) { - // It's safe to set the context more than once if it's the same context. - return; - } - DCHECK(g_application_context.Get().is_null()); - g_application_context.Get().Reset(context); -} - void InitReplacementClassLoader(JNIEnv* env, const JavaRef<jobject>& class_loader) { DCHECK(g_class_loader.Get().is_null()); @@ -105,11 +92,6 @@ g_class_loader.Get().Reset(class_loader); } -const jobject GetApplicationContext() { - DCHECK(!g_application_context.Get().is_null()); - return g_application_context.Get().obj(); -} - ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { jclass clazz; if (!g_class_loader.Get().is_null()) { @@ -143,8 +125,8 @@ JNIEnv* env, const char* class_name, base::subtle::AtomicWord* atomic_class_id) { - COMPILE_ASSERT(sizeof(subtle::AtomicWord) >= sizeof(jclass), - AtomicWord_SmallerThan_jMethodID); + static_assert(sizeof(subtle::AtomicWord) >= sizeof(jclass), + "AtomicWord can't be smaller than jclass"); subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_class_id); if (value) return reinterpret_cast<jclass>(value); @@ -188,8 +170,8 @@ const char* method_name, const char* jni_signature, base::subtle::AtomicWord* atomic_method_id) { - COMPILE_ASSERT(sizeof(subtle::AtomicWord) >= sizeof(jmethodID), - AtomicWord_SmallerThan_jMethodID); + static_assert(sizeof(subtle::AtomicWord) >= sizeof(jmethodID), + "AtomicWord can't be smaller than jMethodID"); subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_method_id); if (value) return reinterpret_cast<jmethodID>(value);
diff --git a/base/android/jni_android.h b/base/android/jni_android.h index 9df90410..651005e 100644 --- a/base/android/jni_android.h +++ b/base/android/jni_android.h
@@ -10,6 +10,9 @@ #include <string> +// TODO(torne): remove this when callers of GetApplicationContext have been +// fixed to include context_utils.h. http://crbug.com/552419 +#include "base/android/context_utils.h" #include "base/android/scoped_java_ref.h" #include "base/atomicops.h" #include "base/base_export.h" @@ -47,19 +50,12 @@ // Detaches the current thread from VM if it is attached. BASE_EXPORT void DetachFromVM(); -// Initializes the global JVM. It is not necessarily called before -// InitApplicationContext(). +// Initializes the global JVM. BASE_EXPORT void InitVM(JavaVM* vm); // Returns true if the global JVM has been initialized. BASE_EXPORT bool IsVMInitialized(); -// Initializes the global application context object. The |context| can be any -// valid reference to the application context. Internally holds a global ref to -// the context. InitVM and InitApplicationContext maybe called in either order. -BASE_EXPORT void InitApplicationContext(JNIEnv* env, - const JavaRef<jobject>& context); - // Initializes the global ClassLoader used by the GetClass and LazyGetClass // methods. This is needed because JNI will use the base ClassLoader when there // is no Java code on the stack. The base ClassLoader doesn't know about any of @@ -69,11 +65,6 @@ JNIEnv* env, const JavaRef<jobject>& class_loader); -// Gets a global ref to the application context set with -// InitApplicationContext(). Ownership is retained by the function - the caller -// must NOT release it. -const BASE_EXPORT jobject GetApplicationContext(); - // Finds the class named |class_name| and returns it. // Use this method instead of invoking directly the JNI FindClass method (to // prevent leaking local references).
diff --git a/base/atomicops_internals_x86_msvc.h b/base/atomicops_internals_x86_msvc.h index 71ddca2b..6ff0f440 100644 --- a/base/atomicops_internals_x86_msvc.h +++ b/base/atomicops_internals_x86_msvc.h
@@ -109,7 +109,7 @@ // 64-bit low-level operations on 64-bit platform. -COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic); +static_assert(sizeof(Atomic64) == sizeof(PVOID), "atomic word is atomic"); inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, Atomic64 old_value,
diff --git a/base/base.gyp b/base/base.gyp index 2f8738e..41cc36eb 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -1396,6 +1396,7 @@ 'android/java/src/org/chromium/base/BuildInfo.java', 'android/java/src/org/chromium/base/CommandLine.java', 'android/java/src/org/chromium/base/ContentUriUtils.java', + 'android/java/src/org/chromium/base/ContextUtils.java', 'android/java/src/org/chromium/base/CpuFeatures.java', 'android/java/src/org/chromium/base/EventLog.java', 'android/java/src/org/chromium/base/FieldTrialList.java',
diff --git a/base/base.gypi b/base/base.gypi index bdaf4c78..4139688 100644 --- a/base/base.gypi +++ b/base/base.gypi
@@ -34,6 +34,8 @@ 'android/command_line_android.h', 'android/content_uri_utils.cc', 'android/content_uri_utils.h', + 'android/context_utils.cc', + 'android/context_utils.h', 'android/cpu_features.cc', 'android/cxa_demangle_stub.cc', 'android/event_log.cc',
diff --git a/base/bind.h b/base/bind.h index 51be10d..94da5ac 100644 --- a/base/bind.h +++ b/base/bind.h
@@ -89,7 +89,7 @@ // invoked function will receive a reference to the stored copy of the // argument and not the original. static_assert(!internal::HasNonConstReferenceParam<BoundRunType>::value, - "do_not_bind_functions_with_nonconst_ref"); + "do not bind functions with nonconst ref"); const bool is_method = internal::HasIsMethodTag<RunnableType>::value; @@ -98,10 +98,10 @@ // methods. We also disallow binding of an array as the method's target // object. static_assert(!internal::BindsArrayToFirstArg<is_method, Args...>::value, - "first_bound_argument_to_method_cannot_be_array"); + "first bound argument to method cannot be array"); static_assert( !internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value, - "a_parameter_is_refcounted_type_and_needs_scoped_refptr"); + "a parameter is a refcounted type and needs scoped_refptr"); typedef internal::BindState< RunnableType, RunType,
diff --git a/base/bind_internal.h b/base/bind_internal.h index 1cb1684d..c6832e6 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h
@@ -313,8 +313,8 @@ // WeakCalls are only supported for functions with a void return type. // Otherwise, the function result would be undefined if the the WeakPtr<> // is invalidated. - COMPILE_ASSERT(is_void<ReturnType>::value, - weak_ptrs_can_only_bind_to_methods_without_return_values); + static_assert(is_void<ReturnType>::value, + "weak_ptrs can only bind to methods without return values"); }; #endif
diff --git a/base/containers/hash_tables.h b/base/containers/hash_tables.h index 5ce9161..a1244f7 100644 --- a/base/containers/hash_tables.h +++ b/base/containers/hash_tables.h
@@ -247,57 +247,16 @@ return high_bits; } -#define DEFINE_32BIT_PAIR_HASH(Type1, Type2) \ -inline std::size_t HashPair(Type1 value1, Type2 value2) { \ - return HashInts32(value1, value2); \ +template<typename T1, typename T2> +inline std::size_t HashPair(T1 value1, T2 value2) { + // This condition is expected to be compile-time evaluated and optimised away + // in release builds. + if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t))) + return HashInts64(value1, value2); + + return HashInts32(value1, value2); } -DEFINE_32BIT_PAIR_HASH(int16, int16); -DEFINE_32BIT_PAIR_HASH(int16, uint16); -DEFINE_32BIT_PAIR_HASH(int16, int32); -DEFINE_32BIT_PAIR_HASH(int16, uint32); -DEFINE_32BIT_PAIR_HASH(uint16, int16); -DEFINE_32BIT_PAIR_HASH(uint16, uint16); -DEFINE_32BIT_PAIR_HASH(uint16, int32); -DEFINE_32BIT_PAIR_HASH(uint16, uint32); -DEFINE_32BIT_PAIR_HASH(int32, int16); -DEFINE_32BIT_PAIR_HASH(int32, uint16); -DEFINE_32BIT_PAIR_HASH(int32, int32); -DEFINE_32BIT_PAIR_HASH(int32, uint32); -DEFINE_32BIT_PAIR_HASH(uint32, int16); -DEFINE_32BIT_PAIR_HASH(uint32, uint16); -DEFINE_32BIT_PAIR_HASH(uint32, int32); -DEFINE_32BIT_PAIR_HASH(uint32, uint32); - -#undef DEFINE_32BIT_PAIR_HASH - -#define DEFINE_64BIT_PAIR_HASH(Type1, Type2) \ -inline std::size_t HashPair(Type1 value1, Type2 value2) { \ - return HashInts64(value1, value2); \ -} - -DEFINE_64BIT_PAIR_HASH(int16, int64); -DEFINE_64BIT_PAIR_HASH(int16, uint64); -DEFINE_64BIT_PAIR_HASH(uint16, int64); -DEFINE_64BIT_PAIR_HASH(uint16, uint64); -DEFINE_64BIT_PAIR_HASH(int32, int64); -DEFINE_64BIT_PAIR_HASH(int32, uint64); -DEFINE_64BIT_PAIR_HASH(uint32, int64); -DEFINE_64BIT_PAIR_HASH(uint32, uint64); -DEFINE_64BIT_PAIR_HASH(int64, int16); -DEFINE_64BIT_PAIR_HASH(int64, uint16); -DEFINE_64BIT_PAIR_HASH(int64, int32); -DEFINE_64BIT_PAIR_HASH(int64, uint32); -DEFINE_64BIT_PAIR_HASH(int64, int64); -DEFINE_64BIT_PAIR_HASH(int64, uint64); -DEFINE_64BIT_PAIR_HASH(uint64, int16); -DEFINE_64BIT_PAIR_HASH(uint64, uint16); -DEFINE_64BIT_PAIR_HASH(uint64, int32); -DEFINE_64BIT_PAIR_HASH(uint64, uint32); -DEFINE_64BIT_PAIR_HASH(uint64, int64); -DEFINE_64BIT_PAIR_HASH(uint64, uint64); - -#undef DEFINE_64BIT_PAIR_HASH } // namespace base namespace BASE_HASH_NAMESPACE {
diff --git a/base/containers/small_map.h b/base/containers/small_map.h index df3d22a..8ae4219 100644 --- a/base/containers/small_map.h +++ b/base/containers/small_map.h
@@ -187,7 +187,7 @@ // particular, gcc 2.95.3 does it but later versions allow 0-length // arrays. Therefore, we explicitly reject non-positive kArraySize // here. - COMPILE_ASSERT(kArraySize > 0, default_initial_size_should_be_positive); + static_assert(kArraySize > 0, "default initial size should be positive"); public: typedef typename NormalMap::key_type key_type;
diff --git a/base/containers/stack_container.h b/base/containers/stack_container.h index 54090d3..2c7dd65 100644 --- a/base/containers/stack_container.h +++ b/base/containers/stack_container.h
@@ -57,7 +57,7 @@ // buffer of the right size instead. base::AlignedMemory<sizeof(T[stack_capacity]), ALIGNOF(T)> stack_buffer_; #if defined(__GNUC__) && !defined(ARCH_CPU_X86_FAMILY) - COMPILE_ASSERT(ALIGNOF(T) <= 16, crbug_115612); + static_assert(ALIGNOF(T) <= 16, "http://crbug.com/115612"); #endif // Set when the stack buffer is used for an allocation. We do not track
diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc index fb5b21f9..c49a762 100644 --- a/base/debug/stack_trace_posix.cc +++ b/base/debug/stack_trace_posix.cc
@@ -473,7 +473,7 @@ } // Returns a O_RDONLY file descriptor for |file_path| if it was opened - // sucessfully during the initialization. The file is repositioned at + // successfully during the initialization. The file is repositioned at // offset 0. // IMPORTANT: This function must be async-signal-safe because it can be // called from a signal handler (symbolizing stack frames for a crash). @@ -741,7 +741,7 @@ namespace internal { // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc. -char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) { +char* itoa_r(intptr_t i, char* buf, size_t sz, int base, size_t padding) { // Make sure we can write at least one NUL byte. size_t n = 1; if (n > sz) @@ -752,7 +752,7 @@ return NULL; } - char *start = buf; + char* start = buf; uintptr_t j = i; @@ -771,7 +771,7 @@ // Loop until we have converted the entire number. Output at least one // character (i.e. '0'). - char *ptr = start; + char* ptr = start; do { // Make sure there is still enough space left in our output buffer. if (++n > sz) {
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc index a5aee01..9760f04 100644 --- a/base/files/file_posix.cc +++ b/base/files/file_posix.cc
@@ -22,9 +22,9 @@ namespace base { // Make sure our Whence mappings match the system headers. -COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET && - File::FROM_CURRENT == SEEK_CUR && - File::FROM_END == SEEK_END, whence_matches_system); +static_assert(File::FROM_BEGIN == SEEK_SET && File::FROM_CURRENT == SEEK_CUR && + File::FROM_END == SEEK_END, + "whence mapping must match the system headers"); namespace { @@ -184,11 +184,11 @@ SCOPED_FILE_TRACE_WITH_SIZE("Seek", offset); #if defined(OS_ANDROID) - COMPILE_ASSERT(sizeof(int64) == sizeof(off64_t), off64_t_64_bit); + static_assert(sizeof(int64) == sizeof(off64_t), "off64_t must be 64 bits"); return lseek64(file_.get(), static_cast<off64_t>(offset), static_cast<int>(whence)); #else - COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); + static_assert(sizeof(int64) == sizeof(off_t), "off_t must be 64 bits"); return lseek(file_.get(), static_cast<off_t>(offset), static_cast<int>(whence)); #endif @@ -471,7 +471,7 @@ else if (flags & FLAG_APPEND) open_flags |= O_APPEND | O_WRONLY; - COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero); + static_assert(O_RDONLY == 0, "O_RDONLY must equal zero"); int mode = S_IRUSR | S_IWUSR; #if defined(OS_CHROMEOS)
diff --git a/base/files/file_win.cc b/base/files/file_win.cc index 2d75ca2..c2cc3ab 100644 --- a/base/files/file_win.cc +++ b/base/files/file_win.cc
@@ -13,9 +13,10 @@ namespace base { // Make sure our Whence mappings match the system headers. -COMPILE_ASSERT(File::FROM_BEGIN == FILE_BEGIN && - File::FROM_CURRENT == FILE_CURRENT && - File::FROM_END == FILE_END, whence_matches_system); +static_assert(File::FROM_BEGIN == FILE_BEGIN && + File::FROM_CURRENT == FILE_CURRENT && + File::FROM_END == FILE_END, + "whence mapping must match the system headers"); bool File::IsValid() const { return file_.IsValid();
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc index 2050b0ff..015df43 100644 --- a/base/json/json_reader.cc +++ b/base/json/json_reader.cc
@@ -11,8 +11,8 @@ namespace base { // Values 1000 and above are used by JSONFileValueSerializer::JsonFileError. -COMPILE_ASSERT(JSONReader::JSON_PARSE_ERROR_COUNT < 1000, - json_reader_error_out_of_bounds); +static_assert(JSONReader::JSON_PARSE_ERROR_COUNT < 1000, + "JSONReader error out of bounds"); const char JSONReader::kInvalidEscape[] = "Invalid escape sequence.";
diff --git a/base/json/string_escape.cc b/base/json/string_escape.cc index f5d6a76..3221a3c 100644 --- a/base/json/string_escape.cc +++ b/base/json/string_escape.cc
@@ -23,7 +23,7 @@ const uint32 kReplacementCodePoint = 0xFFFD; // Used below in EscapeSpecialCodePoint(). -COMPILE_ASSERT('<' == 0x3C, less_than_sign_is_0x3c); +static_assert('<' == 0x3C, "less than sign must be 0x3c"); // Try to escape the |code_point| if it is a known special character. If // successful, returns true and appends the escape sequence to |dest|. This
diff --git a/base/logging.h b/base/logging.h index 8c7f20ad..a78b786 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -952,9 +952,9 @@ #define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS #elif NOTIMPLEMENTED_POLICY == 1 // TODO, figure out how to generate a warning -#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED) +#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED") #elif NOTIMPLEMENTED_POLICY == 2 -#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED) +#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED") #elif NOTIMPLEMENTED_POLICY == 3 #define NOTIMPLEMENTED() NOTREACHED() #elif NOTIMPLEMENTED_POLICY == 4
diff --git a/base/mac/foundation_util_unittest.mm b/base/mac/foundation_util_unittest.mm index c688442a..69d5b1fd 100644 --- a/base/mac/foundation_util_unittest.mm +++ b/base/mac/foundation_util_unittest.mm
@@ -281,8 +281,8 @@ CFStringRef keys[] = { CFSTR("one"), CFSTR("two"), CFSTR("three") }; CFNumberRef values[] = { cf_one, cf_two, cf_three }; - COMPILE_ASSERT(arraysize(keys) == arraysize(values), - keys_and_values_arraysizes_are_different); + static_assert(arraysize(keys) == arraysize(values), + "keys and values arrays must have the same size"); ScopedCFTypeRef<CFDictionaryRef> test_dict( CFDictionaryCreate(kCFAllocatorDefault,
diff --git a/base/macros.h b/base/macros.h index c5f503f..65c7749 100644 --- a/base/macros.h +++ b/base/macros.h
@@ -129,7 +129,8 @@ template <class Dest, class Source> inline Dest bit_cast(const Source& source) { - COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual); + static_assert(sizeof(Dest) == sizeof(Source), + "bit_cast requires source and destination to be the same size"); Dest dest; memcpy(&dest, &source, sizeof(dest));
diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h index b3d5a35d..51750d3 100644 --- a/base/memory/scoped_ptr.h +++ b/base/memory/scoped_ptr.h
@@ -239,8 +239,8 @@ class scoped_ptr { MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) - COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, - T_is_refcounted_type_and_needs_scoped_refptr); + static_assert(base::internal::IsNotRefCounted<T>::value, + "T is a refcounted type and needs a scoped_refptr"); public: // The element and deleter types.
diff --git a/base/memory/scoped_ptr_unittest.cc b/base/memory/scoped_ptr_unittest.cc index 6330bb9e..60a050e 100644 --- a/base/memory/scoped_ptr_unittest.cc +++ b/base/memory/scoped_ptr_unittest.cc
@@ -102,8 +102,8 @@ int constructed = 0; // Ensure size of scoped_ptr<> doesn't increase unexpectedly. - COMPILE_ASSERT(sizeof(int*) >= sizeof(scoped_ptr<int>), - scoped_ptr_larger_than_raw_ptr); + static_assert(sizeof(int*) >= sizeof(scoped_ptr<int>), + "scoped_ptr shouldn't be larger than the raw pointer"); { scoped_ptr<ConDecLogger> scoper(new ConDecLogger(&constructed));
diff --git a/base/memory/shared_memory.h b/base/memory/shared_memory.h index 5cdcb0d..18416c0 100644 --- a/base/memory/shared_memory.h +++ b/base/memory/shared_memory.h
@@ -140,10 +140,6 @@ // http://crbug.com/466437. bool CreateAndMapAnonymousPosix(size_t size); bool CreateAnonymousPosix(size_t size); - - // This method is an analog of CreateAndMapAnonymous that forces the - // underlying OS primitive to be a Mach memory object. - bool CreateAndMapAnonymousMach(size_t size); #endif // defined(OS_MACOSX) && !defined(OS_IOS) // Creates an anonymous shared memory segment of size size.
diff --git a/base/memory/shared_memory_mac.cc b/base/memory/shared_memory_mac.cc index 61ebf89..cdf0bc9f 100644 --- a/base/memory/shared_memory_mac.cc +++ b/base/memory/shared_memory_mac.cc
@@ -53,7 +53,7 @@ group = SharedMemoryHandle::POSIX; found_group = true; } else { - group = SharedMemoryHandle::POSIX; + group = SharedMemoryHandle::MACH; } return group; @@ -175,10 +175,20 @@ } // namespace SharedMemoryCreateOptions::SharedMemoryCreateOptions() - : type(SharedMemoryHandle::POSIX), + : type(SharedMemoryHandle::MACH), size(0), executable(false), - share_read_only(false) {} + share_read_only(false) { + if (mac::IsOSLionOrLater()) { + // A/B test the mechanism. Once the experiment is over, this will always be + // set to SharedMemoryHandle::MACH. + // http://crbug.com/547261 + type = GetABTestMechanism(); + } else { + // Mach shared memory isn't supported on OSX 10.6 or older. + type = SharedMemoryHandle::POSIX; + } +} SharedMemory::SharedMemory() : mapped_memory_mechanism_(SharedMemoryHandle::POSIX), @@ -263,22 +273,6 @@ return Create(options); } -bool SharedMemory::CreateAndMapAnonymousMach(size_t size) { - SharedMemoryCreateOptions options; - - if (mac::IsOSLionOrLater()) { - // A/B test the mechanism. Once the experiment is over, this will always be - // set to SharedMemoryHandle::MACH. - // http://crbug.com/547261 - options.type = GetABTestMechanism(); - } else { - // Mach shared memory isn't supported on OSX 10.6 or older. - options.type = SharedMemoryHandle::POSIX; - } - options.size = size; - return Create(options) && Map(size); -} - // static bool SharedMemory::GetSizeFromSharedMemoryHandle( const SharedMemoryHandle& handle,
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc index 37b4086..561c065 100644 --- a/base/memory/shared_memory_unittest.cc +++ b/base/memory/shared_memory_unittest.cc
@@ -473,6 +473,10 @@ SharedMemoryCreateOptions options; options.size = kTestSize; options.executable = true; +#if defined(OS_MACOSX) && !defined(OS_IOS) + // The Mach functionality is tested in shared_memory_mac_unittest.cc. + options.type = SharedMemoryHandle::POSIX; +#endif EXPECT_TRUE(shared_memory.Create(options)); EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
diff --git a/base/memory/singleton_unittest.cc b/base/memory/singleton_unittest.cc index e8788bab..28daf106 100644 --- a/base/memory/singleton_unittest.cc +++ b/base/memory/singleton_unittest.cc
@@ -9,7 +9,8 @@ namespace base { namespace { -COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a); +static_assert(DefaultSingletonTraits<int>::kRegisterAtExit == true, + "object must be deleted on process exit"); typedef void (*CallbackFunc)();
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h index c335ae98..c62f29c 100644 --- a/base/memory/weak_ptr.h +++ b/base/memory/weak_ptr.h
@@ -161,8 +161,8 @@ static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { typedef is_convertible<Derived, internal::SupportsWeakPtrBase&> convertible; - COMPILE_ASSERT(convertible::value, - AsWeakPtr_argument_inherits_from_SupportsWeakPtr); + static_assert(convertible::value, + "AsWeakPtr argument must inherit from SupportsWeakPtr"); return AsWeakPtrImpl<Derived>(t, *t); }
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index 77edfdb..6e4be9dc 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h
@@ -601,8 +601,8 @@ // Do not add any member variables to MessageLoopForUI! This is important b/c // MessageLoopForUI is often allocated via MessageLoop(TYPE_UI). Any extra // data that you need should be stored on the MessageLoop's pump_ instance. -COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUI), - MessageLoopForUI_should_not_have_extra_member_variables); +static_assert(sizeof(MessageLoop) == sizeof(MessageLoopForUI), + "MessageLoopForUI should not have extra member variables"); #endif // !defined(OS_NACL) @@ -682,8 +682,8 @@ // Do not add any member variables to MessageLoopForIO! This is important b/c // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra // data that you need should be stored on the MessageLoop's pump_ instance. -COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), - MessageLoopForIO_should_not_have_extra_member_variables); +static_assert(sizeof(MessageLoop) == sizeof(MessageLoopForIO), + "MessageLoopForIO should not have extra member variables"); } // namespace base
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc index 2ad7517..e9e3be2 100644 --- a/base/metrics/field_trial.cc +++ b/base/metrics/field_trial.cc
@@ -325,12 +325,11 @@ // group number, so that it does not conflict with the |AppendGroup()| // result for the chosen group. const int kNonConflictingGroupNumber = -2; - COMPILE_ASSERT( + static_assert( kNonConflictingGroupNumber != FieldTrial::kDefaultGroupNumber, - conflicting_default_group_number); - COMPILE_ASSERT( - kNonConflictingGroupNumber != FieldTrial::kNotFinalized, - conflicting_default_group_number); + "The 'non-conflicting' group number conflicts"); + static_assert(kNonConflictingGroupNumber != FieldTrial::kNotFinalized, + "The 'non-conflicting' group number conflicts"); *default_group_number = kNonConflictingGroupNumber; } }
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h index b9b4a62..e420494 100644 --- a/base/observer_list_threadsafe.h +++ b/base/observer_list_threadsafe.h
@@ -67,9 +67,8 @@ class UnboundMethod { public: UnboundMethod(Method m, const Params& p) : m_(m), p_(p) { - COMPILE_ASSERT( - (internal::ParamsUseScopedRefptrCorrectly<Params>::value), - badunboundmethodparams); + static_assert((internal::ParamsUseScopedRefptrCorrectly<Params>::value), + "bad unbound method params"); } void Run(T* obj) const { DispatchToMethod(obj, m_, p_);
diff --git a/base/process/process_linux.cc b/base/process/process_linux.cc index ce3dca1..78000db 100644 --- a/base/process/process_linux.cc +++ b/base/process/process_linux.cc
@@ -140,8 +140,8 @@ // hierarchy there's an entry in the file. We look for a control group // named "/chrome_renderers/background" to determine if the process is // backgrounded. crbug.com/548818. - std::vector<StringPiece> lines = - SplitStringPiece(cgroup_contents, "\n", TRIM_WHITESPACE, SPLIT_WANT_ALL); + std::vector<StringPiece> lines = SplitStringPiece( + cgroup_contents, "\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); for (const auto& line : lines) { std::vector<StringPiece> fields = SplitStringPiece(line, ":", TRIM_WHITESPACE, SPLIT_WANT_ALL);
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc index 914a8edc..6ff5e7f 100644 --- a/base/process/process_unittest.cc +++ b/base/process/process_unittest.cc
@@ -208,10 +208,10 @@ // Tests that the function IsProcessBackgroundedCGroup() can parse the contents // of the /proc/<pid>/cgroup file successfully. TEST_F(ProcessTest, TestIsProcessBackgroundedCGroup) { - const char kNotBackgrounded[] = "5:cpuacct,cpu,cpuset:/daemons"; + const char kNotBackgrounded[] = "5:cpuacct,cpu,cpuset:/daemons\n"; const char kBackgrounded[] = "2:freezer:/chrome_renderers/to_be_frozen\n" - "1:cpu:/chrome_renderers/background"; + "1:cpu:/chrome_renderers/background\n"; EXPECT_FALSE(IsProcessBackgroundedCGroup(kNotBackgrounded)); EXPECT_TRUE(IsProcessBackgroundedCGroup(kBackgrounded));
diff --git a/base/profiler/native_stack_sampler_win.cc b/base/profiler/native_stack_sampler_win.cc index 167dc25..7b41fee 100644 --- a/base/profiler/native_stack_sampler_win.cc +++ b/base/profiler/native_stack_sampler_win.cc
@@ -148,7 +148,7 @@ for (; (i < max_stack_size) && context->Rip; ++i) { instruction_pointers[i] = reinterpret_cast<const void*>(context->Rip); if (!frame_unwinder.TryUnwind(context, &modules[i])) - return i + 1; + return i; } return i; #else
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc index a169c9d0..2ba769f 100644 --- a/base/profiler/stack_sampling_profiler_unittest.cc +++ b/base/profiler/stack_sampling_profiler_unittest.cc
@@ -515,15 +515,14 @@ << FormatSampleForDiagnosticOutput(sample, profile.modules); if (wait_until_unloaded) { - // The stack should look like this, resulting in two frames between - // SignalAndWaitUntilSignaled and the last frame, which should be the one in - // the now-unloaded library: + // The stack should look like this, resulting one frame after + // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is not + // recorded since we can't get module information. // // ... WaitableEvent and system frames ... // TargetThread::SignalAndWaitUntilSignaled // TargetThread::OtherLibraryCallback - // InvokeCallbackFunction (in other library, now unloaded) - EXPECT_EQ(2, (sample.end() - 1) - end_frame) + EXPECT_EQ(2, sample.end() - end_frame) << "Stack:\n" << FormatSampleForDiagnosticOutput(sample, profile.modules); } else {
diff --git a/base/rand_util.cc b/base/rand_util.cc index e12088e..1a3b79e5 100644 --- a/base/rand_util.cc +++ b/base/rand_util.cc
@@ -38,7 +38,8 @@ // produce output in the range [0, 1). For IEEE 754 doubles, the mantissa // is expected to accommodate 53 bits. - COMPILE_ASSERT(std::numeric_limits<double>::radix == 2, otherwise_use_scalbn); + static_assert(std::numeric_limits<double>::radix == 2, + "otherwise use scalbn"); static const int kBits = std::numeric_limits<double>::digits; uint64_t random_bits = bits & ((UINT64_C(1) << kBits) - 1); double result = ldexp(static_cast<double>(random_bits), -1 * kBits);
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc index 6aa1cbe..9719abd 100644 --- a/base/strings/safe_sprintf.cc +++ b/base/strings/safe_sprintf.cc
@@ -72,7 +72,7 @@ #if defined(NDEBUG) // We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(), // but C++ doesn't allow us to do that for constants. Instead, we have to -// use careful casting and shifting. We later use a COMPILE_ASSERT to +// use careful casting and shifting. We later use a static_assert to // verify that this worked correctly. namespace { const size_t kSSizeMax = kSSizeMaxConst; @@ -110,18 +110,13 @@ : buffer_(buffer), size_(size - 1), // Account for trailing NUL byte count_(0) { -// The following assertion does not build on Mac and Android. This is because -// static_assert only works with compile-time constants, but mac uses -// libstdc++4.2 and android uses stlport, which both don't mark -// numeric_limits::max() as constexp. Likewise, MSVS2013's standard library -// also doesn't mark max() as constexpr yet. cl.exe supports static_cast but -// doesn't really implement constexpr yet so it doesn't complain, but clang -// does. -#if __cplusplus >= 201103 && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \ - !defined(OS_IOS) && !(defined(__clang__) && defined(OS_WIN)) - COMPILE_ASSERT(kSSizeMaxConst == \ - static_cast<size_t>(std::numeric_limits<ssize_t>::max()), - kSSizeMax_is_the_max_value_of_an_ssize_t); +// MSVS2013's standard library doesn't mark max() as constexpr yet. cl.exe +// supports static_cast but doesn't really implement constexpr yet so it doesn't +// complain, but clang does. +#if __cplusplus >= 201103 && !(defined(__clang__) && defined(OS_WIN)) + static_assert(kSSizeMaxConst == + static_cast<size_t>(std::numeric_limits<ssize_t>::max()), + "kSSizeMaxConst should be the max value of an ssize_t"); #endif DEBUG_CHECK(size > 0); DEBUG_CHECK(size <= kSSizeMax);
diff --git a/base/strings/string16.h b/base/strings/string16.h index 1a01a96..ba4ffe7 100644 --- a/base/strings/string16.h +++ b/base/strings/string16.h
@@ -64,7 +64,8 @@ // int_type needs to be able to hold each possible value of char_type, and in // addition, the distinct value of eof(). - COMPILE_ASSERT(sizeof(int_type) > sizeof(char_type), unexpected_type_width); + static_assert(sizeof(int_type) > sizeof(char_type), + "int must be larger than 16 bits wide"); typedef std::streamoff off_type; typedef mbstate_t state_type;
diff --git a/base/sync_socket_unittest.cc b/base/sync_socket_unittest.cc index 7c8c97cb..0a2f3a7e 100644 --- a/base/sync_socket_unittest.cc +++ b/base/sync_socket_unittest.cc
@@ -49,7 +49,7 @@ void SendReceivePeek(base::SyncSocket* socket_a, base::SyncSocket* socket_b) { int received = 0; const int kSending = 123; - COMPILE_ASSERT(sizeof(kSending) == sizeof(received), Invalid_Data_Size); + static_assert(sizeof(kSending) == sizeof(received), "invalid data size"); ASSERT_EQ(0u, socket_a->Peek()); ASSERT_EQ(0u, socket_b->Peek());
diff --git a/base/sync_socket_win.cc b/base/sync_socket_win.cc index e16b925..4b5040cc 100644 --- a/base/sync_socket_win.cc +++ b/base/sync_socket_win.cc
@@ -121,7 +121,7 @@ DWORD timeout_in_ms) { ThreadRestrictions::AssertIOAllowed(); // The buffer must be byte size or the length check won't make much sense. - COMPILE_ASSERT(sizeof(buffer[0]) == sizeof(char), incorrect_buffer_type); + static_assert(sizeof(buffer[0]) == sizeof(char), "incorrect buffer type"); DCHECK_GT(length, 0u); DCHECK_LE(length, kMaxMessageLength); DCHECK_NE(file, SyncSocket::kInvalidHandle);
diff --git a/base/template_util_unittest.cc b/base/template_util_unittest.cc index 3ec3887..32883f2 100644 --- a/base/template_util_unittest.cc +++ b/base/template_util_unittest.cc
@@ -18,23 +18,24 @@ class Child : public Parent {}; // is_pointer<Type> -COMPILE_ASSERT(!is_pointer<int>::value, IsPointer); -COMPILE_ASSERT(!is_pointer<int&>::value, IsPointer); -COMPILE_ASSERT(is_pointer<int*>::value, IsPointer); -COMPILE_ASSERT(is_pointer<const int*>::value, IsPointer); +static_assert(!is_pointer<int>::value, "IsPointer"); +static_assert(!is_pointer<int&>::value, "IsPointer"); +static_assert(is_pointer<int*>::value, "IsPointer"); +static_assert(is_pointer<const int*>::value, "IsPointer"); // is_array<Type> -COMPILE_ASSERT(!is_array<int>::value, IsArray); -COMPILE_ASSERT(!is_array<int*>::value, IsArray); -COMPILE_ASSERT(!is_array<int(*)[3]>::value, IsArray); -COMPILE_ASSERT(is_array<int[]>::value, IsArray); -COMPILE_ASSERT(is_array<const int[]>::value, IsArray); -COMPILE_ASSERT(is_array<int[3]>::value, IsArray); +static_assert(!is_array<int>::value, "IsArray"); +static_assert(!is_array<int*>::value, "IsArray"); +static_assert(!is_array<int (*)[3]>::value, "IsArray"); +static_assert(is_array<int[]>::value, "IsArray"); +static_assert(is_array<const int[]>::value, "IsArray"); +static_assert(is_array<int[3]>::value, "IsArray"); // is_non_const_reference<Type> -COMPILE_ASSERT(!is_non_const_reference<int>::value, IsNonConstReference); -COMPILE_ASSERT(!is_non_const_reference<const int&>::value, IsNonConstReference); -COMPILE_ASSERT(is_non_const_reference<int&>::value, IsNonConstReference); +static_assert(!is_non_const_reference<int>::value, "IsNonConstReference"); +static_assert(!is_non_const_reference<const int&>::value, + "IsNonConstReference"); +static_assert(is_non_const_reference<int&>::value, "IsNonConstReference"); // is_convertible<From, To> @@ -44,66 +45,64 @@ // (is_convertible < Child), (Parent > ::value) // // Silly C++. -COMPILE_ASSERT( (is_convertible<Child, Parent>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<Parent, Child>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<Parent, AStruct>::value), IsConvertible); -COMPILE_ASSERT( (is_convertible<int, double>::value), IsConvertible); -COMPILE_ASSERT( (is_convertible<int*, void*>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<void*, int*>::value), IsConvertible); +static_assert((is_convertible<Child, Parent>::value), "IsConvertible"); +static_assert(!(is_convertible<Parent, Child>::value), "IsConvertible"); +static_assert(!(is_convertible<Parent, AStruct>::value), "IsConvertible"); +static_assert((is_convertible<int, double>::value), "IsConvertible"); +static_assert((is_convertible<int*, void*>::value), "IsConvertible"); +static_assert(!(is_convertible<void*, int*>::value), "IsConvertible"); // Array types are an easy corner case. Make sure to test that // it does indeed compile. -COMPILE_ASSERT(!(is_convertible<int[10], double>::value), IsConvertible); -COMPILE_ASSERT(!(is_convertible<double, int[10]>::value), IsConvertible); -COMPILE_ASSERT( (is_convertible<int[10], int*>::value), IsConvertible); +static_assert(!(is_convertible<int[10], double>::value), "IsConvertible"); +static_assert(!(is_convertible<double, int[10]>::value), "IsConvertible"); +static_assert((is_convertible<int[10], int*>::value), "IsConvertible"); // is_same<Type1, Type2> -COMPILE_ASSERT(!(is_same<Child, Parent>::value), IsSame); -COMPILE_ASSERT(!(is_same<Parent, Child>::value), IsSame); -COMPILE_ASSERT( (is_same<Parent, Parent>::value), IsSame); -COMPILE_ASSERT( (is_same<int*, int*>::value), IsSame); -COMPILE_ASSERT( (is_same<int, int>::value), IsSame); -COMPILE_ASSERT( (is_same<void, void>::value), IsSame); -COMPILE_ASSERT(!(is_same<int, double>::value), IsSame); - +static_assert(!(is_same<Child, Parent>::value), "IsSame"); +static_assert(!(is_same<Parent, Child>::value), "IsSame"); +static_assert((is_same<Parent, Parent>::value), "IsSame"); +static_assert((is_same<int*, int*>::value), "IsSame"); +static_assert((is_same<int, int>::value), "IsSame"); +static_assert((is_same<void, void>::value), "IsSame"); +static_assert(!(is_same<int, double>::value), "IsSame"); // is_class<Type> -COMPILE_ASSERT(is_class<AStruct>::value, IsClass); -COMPILE_ASSERT(is_class<AClass>::value, IsClass); -COMPILE_ASSERT(!is_class<AnEnum>::value, IsClass); -COMPILE_ASSERT(!is_class<int>::value, IsClass); -COMPILE_ASSERT(!is_class<char*>::value, IsClass); -COMPILE_ASSERT(!is_class<int&>::value, IsClass); -COMPILE_ASSERT(!is_class<char[3]>::value, IsClass); +static_assert(is_class<AStruct>::value, "IsClass"); +static_assert(is_class<AClass>::value, "IsClass"); +static_assert(!is_class<AnEnum>::value, "IsClass"); +static_assert(!is_class<int>::value, "IsClass"); +static_assert(!is_class<char*>::value, "IsClass"); +static_assert(!is_class<int&>::value, "IsClass"); +static_assert(!is_class<char[3]>::value, "IsClass"); +static_assert(!is_member_function_pointer<int>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<int*>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<void*>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<AStruct>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<AStruct*>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<void (*)()>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<int (*)(int)>::value, + "IsMemberFunctionPointer"); +static_assert(!is_member_function_pointer<int (*)(int, int)>::value, + "IsMemberFunctionPointer"); -COMPILE_ASSERT(!is_member_function_pointer<int>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<int*>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<void*>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<AStruct>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<AStruct*>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<void(*)()>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<int(*)(int)>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(!is_member_function_pointer<int(*)(int, int)>::value, - IsMemberFunctionPointer); - -COMPILE_ASSERT(is_member_function_pointer<void (AStruct::*)()>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<void (AStruct::*)(int)>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<int (AStruct::*)(int)>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<int (AStruct::*)(int) const>::value, - IsMemberFunctionPointer); -COMPILE_ASSERT(is_member_function_pointer<int (AStruct::*)(int, int)>::value, - IsMemberFunctionPointer); +static_assert(is_member_function_pointer<void (AStruct::*)()>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<void (AStruct::*)(int)>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<int (AStruct::*)(int)>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<int (AStruct::*)(int) const>::value, + "IsMemberFunctionPointer"); +static_assert(is_member_function_pointer<int (AStruct::*)(int, int)>::value, + "IsMemberFunctionPointer"); } // namespace } // namespace base
diff --git a/base/threading/thread.cc b/base/threading/thread.cc index c775fe74..9d1ca8ef 100644 --- a/base/threading/thread.cc +++ b/base/threading/thread.cc
@@ -262,8 +262,12 @@ com_initializer.reset(); #endif - // Assert that MessageLoop::QuitWhenIdle was called by ThreadQuitHelper. - DCHECK(GetThreadWasQuitProperly()); + if (message_loop->type() != MessageLoop::TYPE_CUSTOM) { + // Assert that MessageLoop::QuitWhenIdle was called by ThreadQuitHelper. + // Don't check for custom message pumps, because their shutdown might not + // allow this. + DCHECK(GetThreadWasQuitProperly()); + } // We can't receive messages anymore. // (The message loop is destructed at the end of this block)
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 2d78c9b..b124c9f 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -75,6 +75,10 @@ class WindowResizeHelperMac; } +namespace views { +class WindowManagerConnection; +} + namespace base { namespace android { @@ -221,6 +225,7 @@ #if !defined(OFFICIAL_BUILD) friend class content::SoftwareOutputDeviceMus; // Interim non-production code #endif + friend class views::WindowManagerConnection; // END USAGE THAT NEEDS TO BE FIXED. #if ENABLE_THREAD_RESTRICTIONS
diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc index 578e039..139e0c9e 100644 --- a/base/time/time_mac.cc +++ b/base/time/time_mac.cc
@@ -135,8 +135,8 @@ // static Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) { - COMPILE_ASSERT(std::numeric_limits<CFAbsoluteTime>::has_infinity, - numeric_limits_infinity_is_undefined_when_not_has_infinity); + static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, + "CFAbsoluteTime must have an infinity value"); if (t == 0) return Time(); // Consider 0 as a null Time. if (t == std::numeric_limits<CFAbsoluteTime>::infinity()) @@ -147,8 +147,8 @@ } CFAbsoluteTime Time::ToCFAbsoluteTime() const { - COMPILE_ASSERT(std::numeric_limits<CFAbsoluteTime>::has_infinity, - numeric_limits_infinity_is_undefined_when_not_has_infinity); + static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, + "CFAbsoluteTime must have an infinity value"); if (is_null()) return 0; // Consider 0 as a null Time. if (is_max())
diff --git a/base/time/time_win_unittest.cc b/base/time/time_win_unittest.cc index 38798d5..baaa322 100644 --- a/base/time/time_win_unittest.cc +++ b/base/time/time_win_unittest.cc
@@ -187,8 +187,8 @@ }; // Cheating a bit here: assumes sizeof(TimeTicks) == sizeof(Time) // in order to create a single test case list. - COMPILE_ASSERT(sizeof(TimeTicks) == sizeof(Time), - test_only_works_with_same_sizes); + static_assert(sizeof(TimeTicks) == sizeof(Time), + "TimeTicks and Time must be the same size"); std::vector<TestCase> cases; cases.push_back({reinterpret_cast<TestFunc>(&Time::Now), "Time::Now"}); cases.push_back({&TimeTicks::Now, "TimeTicks::Now"});
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc index b58fb60..51e4590f 100644 --- a/base/trace_event/heap_profiler_allocation_context_tracker.cc +++ b/base/trace_event/heap_profiler_allocation_context_tracker.cc
@@ -5,6 +5,7 @@ #include "base/trace_event/heap_profiler_allocation_context_tracker.h" #include <algorithm> +#include <iterator> #include "base/atomicops.h" #include "base/threading/thread_local_storage.h" @@ -25,13 +26,6 @@ delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker); } -// Returns a pointer past the end of the fixed-size array |array| of |T| of -// length |N|, identical to C++11 |std::end|. -template <typename T, int N> -T* End(T(&array)[N]) { - return array + N; -} - } // namespace AllocationContextTracker::AllocationContextTracker() {} @@ -99,9 +93,9 @@ // Fill the backtrace. { auto src = tracker->pseudo_stack_.begin(); - auto dst = ctx.backtrace.frames; + auto dst = std::begin(ctx.backtrace.frames); auto src_end = tracker->pseudo_stack_.end(); - auto dst_end = End(ctx.backtrace.frames); + auto dst_end = std::end(ctx.backtrace.frames); // Copy as much of the bottom of the pseudo stack into the backtrace as // possible.
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc b/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc index fe3f407..130a927 100644 --- a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc +++ b/base/trace_event/heap_profiler_allocation_context_tracker_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 <iterator> + #include "base/memory/ref_counted.h" #include "base/trace_event/heap_profiler_allocation_context.h" #include "base/trace_event/heap_profiler_allocation_context_tracker.h" @@ -19,23 +21,16 @@ const char kFroyo[] = "Froyo"; const char kGingerbread[] = "Gingerbread"; -// Returns a pointer past the end of the fixed-size array |array| of |T| of -// length |N|, identical to C++11 |std::end|. -template <typename T, int N> -const T* End(const T(&array)[N]) { - return array + N; -} - // Asserts that the fixed-size array |expected_backtrace| matches the backtrace // in |AllocationContextTracker::GetContextSnapshot|. template <size_t N> void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) { AllocationContext ctx = AllocationContextTracker::GetContextSnapshot(); - auto actual = ctx.backtrace.frames; - auto actual_bottom = End(ctx.backtrace.frames); - auto expected = expected_backtrace; - auto expected_bottom = End(expected_backtrace); + auto actual = std::begin(ctx.backtrace.frames); + auto actual_bottom = std::end(ctx.backtrace.frames); + auto expected = std::begin(expected_backtrace); + auto expected_bottom = std::end(expected_backtrace); // Note that this requires the pointers to be equal, this is not doing a deep // string comparison.
diff --git a/base/win/i18n.cc b/base/win/i18n.cc index 9e523a1..a26e274 100644 --- a/base/win/i18n.cc +++ b/base/win/i18n.cc
@@ -32,8 +32,9 @@ &kThreadLanguagesFunctionName[0] }; -COMPILE_ASSERT(NUM_FUNCTIONS == arraysize(kLanguageFunctionNames), - language_function_enum_and_names_out_of_sync); +static_assert(NUM_FUNCTIONS == arraysize(kLanguageFunctionNames), + "LanguageFunction enum and kLanguageFunctionNames array must be " + "kept in sync"); // Calls one of the MUI Get*PreferredUILanguages functions, placing the result // in |languages|. |function| identifies the function to call and |flags| is
diff --git a/base/win/iat_patch_function.cc b/base/win/iat_patch_function.cc index 31659c6c..be7c545b 100644 --- a/base/win/iat_patch_function.cc +++ b/base/win/iat_patch_function.cc
@@ -67,8 +67,9 @@ } // portability check - COMPILE_ASSERT(sizeof(iat->u1.Function) == - sizeof(intercept_information->new_function), unknown_IAT_thunk_format); + static_assert( + sizeof(iat->u1.Function) == sizeof(intercept_information->new_function), + "unknown IAT thunk format"); // Patch the function. intercept_information->return_code =
diff --git a/base/win/scoped_bstr.cc b/base/win/scoped_bstr.cc index 63ade0c..298318db 100644 --- a/base/win/scoped_bstr.cc +++ b/base/win/scoped_bstr.cc
@@ -14,7 +14,7 @@ } ScopedBstr::~ScopedBstr() { - COMPILE_ASSERT(sizeof(ScopedBstr) == sizeof(BSTR), ScopedBstrSize); + static_assert(sizeof(ScopedBstr) == sizeof(BSTR), "ScopedBstrSize"); SysFreeString(bstr_); }
diff --git a/base/win/scoped_comptr.h b/base/win/scoped_comptr.h index ade12fe..5ce60e2 100644 --- a/base/win/scoped_comptr.h +++ b/base/win/scoped_comptr.h
@@ -43,8 +43,9 @@ ~ScopedComPtr() { // We don't want the smart pointer class to be bigger than the pointer // it wraps. - COMPILE_ASSERT(sizeof(ScopedComPtr<Interface, interface_id>) == - sizeof(Interface*), ScopedComPtrSize); + static_assert( + sizeof(ScopedComPtr<Interface, interface_id>) == sizeof(Interface*), + "ScopedComPtrSize"); } // Explicit Release() of the held object. Useful for reuse of the
diff --git a/base/win/scoped_variant.cc b/base/win/scoped_variant.cc index 2cf2657..4a1ad90 100644 --- a/base/win/scoped_variant.cc +++ b/base/win/scoped_variant.cc
@@ -12,7 +12,7 @@ const VARIANT ScopedVariant::kEmptyVariant = {{{VT_EMPTY}}}; ScopedVariant::~ScopedVariant() { - COMPILE_ASSERT(sizeof(ScopedVariant) == sizeof(VARIANT), ScopedVariantSize); + static_assert(sizeof(ScopedVariant) == sizeof(VARIANT), "ScopedVariantSize"); ::VariantClear(&var_); }
diff --git a/blimp/client/android/blimp_library_loader.cc b/blimp/client/android/blimp_library_loader.cc index 495d9d1..9668850 100644 --- a/blimp/client/android/blimp_library_loader.cc +++ b/blimp/client/android/blimp_library_loader.cc
@@ -60,10 +60,7 @@ namespace blimp { static jboolean InitializeBlimp(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - const JavaParamRef<jobject>& jcontext) { - base::android::InitApplicationContext(env, jcontext); - + const JavaParamRef<jclass>& clazz) { // TODO(dtrainor): Start the runner? return true; }
diff --git a/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java b/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java index 7166e2b9..7d6f22a 100644 --- a/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java +++ b/blimp/client/android/java/src/org/chromium/blimp/BlimpLibraryLoader.java
@@ -7,6 +7,7 @@ import android.content.Context; import android.os.Handler; +import org.chromium.base.ContextUtils; import org.chromium.base.ObserverList; import org.chromium.base.ResourceExtractor; import org.chromium.base.ThreadUtils; @@ -90,7 +91,8 @@ extractor.addCompletionCallback(new Runnable() { @Override public void run() { - final boolean initResult = nativeInitializeBlimp(context.getApplicationContext()); + ContextUtils.initApplicationContext(context.getApplicationContext()); + final boolean initResult = nativeInitializeBlimp(); new Handler().post(new Runnable() { @Override public void run() { @@ -126,6 +128,6 @@ } // Native methods. - private static native boolean nativeInitializeBlimp(Context context); + private static native boolean nativeInitializeBlimp(); private static native boolean nativeStartBlimp(); }
diff --git a/blimp/common/proto/blimp_message.proto b/blimp/common/proto/blimp_message.proto index e81c608..9b116841 100644 --- a/blimp/common/proto/blimp_message.proto +++ b/blimp/common/proto/blimp_message.proto
@@ -33,10 +33,11 @@ message BlimpMessage { enum Type { - COMPOSITOR = 0; - INPUT = 1; - CONTROL = 2; - NAVIGATION = 3; + UNKNOWN = 0; + COMPOSITOR = 1; + INPUT = 2; + CONTROL = 3; + NAVIGATION = 4; } // Identifies the feature type of this message. // The feature-specific contents are contained in optional fields of the same
diff --git a/blimp/common/proto/control.proto b/blimp/common/proto/control.proto index f01654b..bcb9aaab 100644 --- a/blimp/common/proto/control.proto +++ b/blimp/common/proto/control.proto
@@ -10,6 +10,8 @@ message ControlMessage { enum Type { + UNKNOWN = 0; + // Client <=> Server types. CREATE_TAB = 1; CLOSE_TAB = 2;
diff --git a/blimp/common/proto/input.proto b/blimp/common/proto/input.proto index 8e793e7..bc05dd3 100644 --- a/blimp/common/proto/input.proto +++ b/blimp/common/proto/input.proto
@@ -27,6 +27,7 @@ message InputMessage { enum Type { + UNKNOWN = 0; CLICK = 1; DRAG = 2; }
diff --git a/blimp/common/proto/navigation.proto b/blimp/common/proto/navigation.proto index 564e1a482..86270e1 100644 --- a/blimp/common/proto/navigation.proto +++ b/blimp/common/proto/navigation.proto
@@ -34,6 +34,8 @@ message NavigationMessage { enum Type { + UNKNOWN = 0; + // Server => Client types. NAVIGATION_STATE_CHANGED = 1;
diff --git a/build/all.gyp b/build/all.gyp index 176e855..352e068f 100644 --- a/build/all.gyp +++ b/build/all.gyp
@@ -473,7 +473,7 @@ }], ['use_aura==1 or toolkit_views==1', { 'dependencies': [ - '../ui/events/events.gyp:events_unittests', + '../ui/events/events_unittests.gyp:events_unittests', ], }], ['use_ash==1', { @@ -831,7 +831,7 @@ '../tools/android/findbugs_plugin/findbugs_plugin.gyp:findbugs_plugin_test', '../ui/android/ui_android.gyp:ui_android_unittests', '../ui/base/ui_base_tests.gyp:ui_base_unittests', - '../ui/events/events.gyp:events_unittests', + '../ui/events/events_unittests.gyp:events_unittests', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests', # Unit test bundles packaged as an apk. '../base/base.gyp:base_unittests_apk', @@ -855,7 +855,7 @@ '../tools/android/heap_profiler/heap_profiler.gyp:heap_profiler_unittests_apk', '../ui/android/ui_android.gyp:ui_android_unittests_apk', '../ui/base/ui_base_tests.gyp:ui_base_unittests_apk', - '../ui/events/events.gyp:events_unittests_apk', + '../ui/events/events_unittests.gyp:events_unittests_apk', '../ui/gfx/gfx_tests.gyp:gfx_unittests_apk', '../ui/gl/gl_tests.gyp:gl_unittests_apk', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_apk', @@ -1091,7 +1091,7 @@ '../tools/perf/clear_system_cache/clear_system_cache.gyp:*', '../tools/telemetry/telemetry.gyp:*', '../ui/base/ui_base_tests.gyp:ui_base_unittests', - '../ui/events/events.gyp:events_unittests', + '../ui/events/events_unittests.gyp:events_unittests', '../ui/gfx/gfx_tests.gyp:gfx_unittests', '../ui/gl/gl_tests.gyp:gl_unittests', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests', @@ -1196,7 +1196,7 @@ '../ui/aura/aura.gyp:aura_unittests', '../ui/compositor/compositor.gyp:compositor_unittests', '../ui/display/display.gyp:display_unittests', - '../ui/events/events.gyp:events_unittests', + '../ui/events/events_unittests.gyp:events_unittests', '../ui/gfx/gfx_tests.gyp:gfx_unittests', '../ui/gl/gl_tests.gyp:gl_unittests', '../ui/keyboard/keyboard.gyp:keyboard_unittests',
diff --git a/build/android/adb_android_webview_command_line b/build/android/adb_android_webview_command_line index 791e270..9075918 100755 --- a/build/android/adb_android_webview_command_line +++ b/build/android/adb_android_webview_command_line
@@ -13,8 +13,5 @@ # To remove all content shell flags, pass an empty string for the flags: # adb_android_webview_command_line "" -. $(dirname $0)/adb_command_line_functions.sh -CMD_LINE_FILE=/data/local/tmp/android-webview-command-line -REQUIRES_SU=0 -set_command_line "$@" - +exec $(dirname $0)/adb_command_line.py --device-path \ + /data/local/tmp/android-webview-command-line "$@"
diff --git a/build/android/adb_blimp_command_line b/build/android/adb_blimp_command_line index 2050ead..1ff3769 100755 --- a/build/android/adb_blimp_command_line +++ b/build/android/adb_blimp_command_line
@@ -13,7 +13,5 @@ # To remove all Blimp flags, pass an empty string for the flags: # adb_blimp_command_line "" -. $(dirname $0)/adb_command_line_functions.sh -CMD_LINE_FILE=/data/local/blimp-command-line -REQUIRES_SU=1 -set_command_line "$@" +exec $(dirname $0)/adb_command_line.py --device-path \ + /data/local/blimp-command-line "$@"
diff --git a/build/android/adb_chrome_public_command_line b/build/android/adb_chrome_public_command_line index 9bf91c6..ac379e8 100755 --- a/build/android/adb_chrome_public_command_line +++ b/build/android/adb_chrome_public_command_line
@@ -13,7 +13,5 @@ # To remove all Chrome flags, pass an empty string for the flags: # adb_chrome_public_command_line "" -. $(dirname $0)/adb_command_line_functions.sh -CMD_LINE_FILE=/data/local/chrome-command-line -REQUIRES_SU=1 -set_command_line "$@" +exec $(dirname $0)/adb_command_line.py --device-path \ + /data/local/chrome-command-line "$@"
diff --git a/build/android/adb_command_line.py b/build/android/adb_command_line.py new file mode 100755 index 0000000..fa3a82b26 --- /dev/null +++ b/build/android/adb_command_line.py
@@ -0,0 +1,83 @@ +#!/usr/bin/python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Utility for reading / writing command-line flag files on device(s).""" + +import argparse +import sys + +from devil.android import device_utils +from devil.android import device_errors +from devil.utils import cmd_helper + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.usage = '''%(prog)s --device-path PATH [--device SERIAL] [flags...] + +No flags: Prints existing command-line file. +Empty string: Deletes command-line file. +Otherwise: Writes command-line file. + +''' + parser.add_argument('-d', '--device', dest='device', + help='Target device for apk to install on.') + parser.add_argument('--device-path', required=True, + help='Remote path to flags file.') + args, remote_args = parser.parse_known_args() + + as_root = not args.device_path.startswith('/data/local/tmp/') + + if args.device: + devices = [device_utils.DeviceUtils(args.device, default_retries=0)] + else: + devices = device_utils.DeviceUtils.HealthyDevices(default_retries=0) + if not devices: + raise device_errors.NoDevicesError() + + all_devices = device_utils.DeviceUtils.parallel(devices) + + def print_args(): + def read_flags(device): + try: + return device.ReadFile(args.device_path, as_root=as_root) + except device_errors.AdbCommandFailedError: + return '\n' # File might not exist. + + descriptions = all_devices.pMap(lambda d: d.build_description).pGet(None) + flags = all_devices.pMap(read_flags).pGet(None) + for d, desc, flags in zip(devices, descriptions, flags): + print ' %s (%s): %s' % (d, desc, flags), + + # No args == print flags. + if not remote_args: + print 'Existing flags (in %s):' % args.device_path + print_args() + return 0 + + # Empty string arg == delete flags file. + if len(remote_args) == 1 and not remote_args[0]: + def delete_flags(device): + device.RunShellCommand(['rm', '-f', args.device_path], as_root=as_root) + all_devices.pMap(delete_flags).pGet(None) + print 'Deleted %s' % args.device_path + return 0 + + # Set flags. + quoted_args = ' '.join(cmd_helper.SingleQuote(x) for x in remote_args) + flags_str = 'chrome %s' % quoted_args + + def write_flags(device): + device.WriteFile(args.device_path, flags_str, as_root=as_root) + device.RunShellCommand(['chmod', '0664', args.device_path], as_root=as_root) + + all_devices.pMap(write_flags).pGet(None) + print 'Wrote flags to %s' % args.device_path + print_args() + return 0 + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/build/android/adb_command_line_functions.sh b/build/android/adb_command_line_functions.sh deleted file mode 100755 index 7ea98b0..0000000 --- a/build/android/adb_command_line_functions.sh +++ /dev/null
@@ -1,40 +0,0 @@ -#!/bin/bash -# -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Variables must be set before calling: -# CMD_LINE_FILE - Path on device to flags file. -# REQUIRES_SU - Set to 1 if path requires root. -function set_command_line() { - SU_CMD="" - if [[ "$REQUIRES_SU" = 1 ]]; then - # Older androids accept "su -c", while newer use "su uid". - SDK_LEVEL=$(adb shell getprop ro.build.version.sdk | tr -d '\r') - # E.g. if no device connected. - if [[ -z "$SDK_LEVEL" ]]; then - exit 1 - fi - SU_CMD="su -c" - if (( $SDK_LEVEL >= 21 )); then - SU_CMD="su 0" - fi - fi - - if [ $# -eq 0 ] ; then - # If nothing specified, print the command line (stripping off "chrome ") - adb shell "cat $CMD_LINE_FILE 2>/dev/null" | cut -d ' ' -s -f2- - elif [ $# -eq 1 ] && [ "$1" = '' ] ; then - # If given an empty string, delete the command line. - set -x - adb shell $SU_CMD rm $CMD_LINE_FILE >/dev/null - else - # Else set it. - set -x - adb shell "echo 'chrome $*' | $SU_CMD dd of=$CMD_LINE_FILE" - # Prevent other apps from modifying flags (this can create security issues). - adb shell $SU_CMD chmod 0664 $CMD_LINE_FILE - fi -} -
diff --git a/build/android/adb_content_shell_command_line b/build/android/adb_content_shell_command_line index 2ac7ece..02ef802 100755 --- a/build/android/adb_content_shell_command_line +++ b/build/android/adb_content_shell_command_line
@@ -13,8 +13,5 @@ # To remove all content shell flags, pass an empty string for the flags: # adb_content_shell_command_line "" -. $(dirname $0)/adb_command_line_functions.sh -CMD_LINE_FILE=/data/local/tmp/content-shell-command-line -REQUIRES_SU=0 -set_command_line "$@" - +exec $(dirname $0)/adb_command_line.py --device-path \ + /data/local/tmp/content-shell-command-line "$@"
diff --git a/build/android/adb_system_webview_command_line b/build/android/adb_system_webview_command_line index a0658ea..376b0b3d 100755 --- a/build/android/adb_system_webview_command_line +++ b/build/android/adb_system_webview_command_line
@@ -13,8 +13,5 @@ # To remove all content shell flags, pass an empty string for the flags: # adb_android_webview_command_line "" -. $(dirname $0)/adb_command_line_functions.sh -CMD_LINE_FILE=/data/local/tmp/webview-command-line -REQUIRES_SU=0 -set_command_line "$@" - +exec $(dirname $0)/adb_command_line.py --device-path \ + /data/local/tmp/webview-command-line "$@"
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index 7e0ce23..404d4da 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -31,6 +31,9 @@ help='GYP-list of files to add as assets in the form ' '"srcPath:zipPath", where ":zipPath" is optional.', default='[]') + parser.add_argument('--write-asset-list', + action='store_true', + help='Whether to create an assets/assets_list file.') parser.add_argument('--uncompressed-assets', help='Same as --assets, except disables compression.', default='[]') @@ -92,16 +95,13 @@ """ # Group all uncompressed assets together in the hope that it will increase # locality of mmap'ed files. - for target_compress_type in (zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED): + for target_compress in (False, True): for path in paths: src_path, dest_path = _SplitAssetPath(path) - compress_type = zipfile.ZIP_DEFLATED - if disable_compression or ( - os.path.splitext(src_path)[1] in _NO_COMPRESS_EXTENSIONS): - compress_type = zipfile.ZIP_STORED - - if target_compress_type == compress_type: + compress = not disable_compression and ( + os.path.splitext(src_path)[1] not in _NO_COMPRESS_EXTENSIONS) + if target_compress == compress: apk_path = 'assets/' + dest_path try: apk.getinfo(apk_path) @@ -109,7 +109,13 @@ raise Exception('Multiple targets specified the asset path: %s' % apk_path) except KeyError: - apk.write(src_path, apk_path, compress_type) + build_utils.AddToZipHermetic(apk, apk_path, src_path=src_path, + compress=compress) + + +def _CreateAssetsList(paths): + """Returns a newline-separated list of asset paths for the given paths.""" + return '\n'.join(_SplitAssetPath(p)[1] for p in sorted(paths)) + '\n' def main(args): @@ -144,40 +150,49 @@ # with finalize_apk(), which sometimes aligns and uncompresses the # native libraries. with zipfile.ZipFile(tmp_apk, 'a', zipfile.ZIP_DEFLATED) as apk: + if options.write_asset_list: + data = _CreateAssetsList( + itertools.chain(options.assets, options.uncompressed_assets)) + build_utils.AddToZipHermetic(apk, 'assets/assets_list', data=data) + _AddAssets(apk, options.assets, disable_compression=False) _AddAssets(apk, options.uncompressed_assets, disable_compression=True) + for path in native_libs: basename = os.path.basename(path) - apk.write(path, 'lib/%s/%s' % (options.android_abi, basename)) + apk_path = 'lib/%s/%s' % (options.android_abi, basename) + build_utils.AddToZipHermetic(apk, apk_path, src_path=path) + for name in options.native_lib_placeholders: # Make it non-empty so that its checksum is non-zero and is not # ignored by md5_check. - apk.writestr('lib/%s/%s' % (options.android_abi, name), ':)', - zipfile.ZIP_STORED) - if options.dex_file: - if options.dex_file.endswith('.zip'): - with zipfile.ZipFile(options.dex_file, 'r') as dex_zip: - for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): - apk.writestr(dex, dex_zip.read(dex)) - else: - apk.write(options.dex_file, 'classes.dex') + apk_path = 'lib/%s/%s.so' % (options.android_abi, name) + build_utils.AddToZipHermetic(apk, apk_path, data=':)') + + if options.dex_file and options.dex_file.endswith('.zip'): + with zipfile.ZipFile(options.dex_file, 'r') as dex_zip: + for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')): + build_utils.AddToZipHermetic(apk, dex, data=dex_zip.read(dex)) + elif options.dex_file: + build_utils.AddToZipHermetic(apk, 'classes.dex', + src_path=options.dex_file) if options.emma_device_jar: # Add EMMA Java resources to APK. with zipfile.ZipFile(options.emma_device_jar, 'r') as emma_device_jar: - for emma_device_jar_entry in emma_device_jar.namelist(): - entry_name_lower = emma_device_jar_entry.lower() - if entry_name_lower.startswith('meta-inf/'): + for apk_path in emma_device_jar.namelist(): + apk_path_lower = apk_path.lower() + if apk_path_lower.startswith('meta-inf/'): continue - if entry_name_lower.endswith('/'): + if apk_path_lower.endswith('/'): continue - if entry_name_lower.endswith('.class'): + if apk_path_lower.endswith('.class'): continue - apk.writestr(emma_device_jar_entry, - emma_device_jar.read(emma_device_jar_entry)) + build_utils.AddToZipHermetic(apk, apk_path, + data=emma_device_jar.read(apk_path)) shutil.move(tmp_apk, options.output_apk) finally:
diff --git a/build/android/gyp/java_cpp_enum.py b/build/android/gyp/java_cpp_enum.py index a82ebc2..9299bce 100755 --- a/build/android/gyp/java_cpp_enum.py +++ b/build/android/gyp/java_cpp_enum.py
@@ -345,7 +345,7 @@ with zipfile.ZipFile(options.srcjar, 'w', zipfile.ZIP_STORED) as srcjar: for output_path, data in DoGenerate(input_paths): - srcjar.writestr(build_utils.CreateHermeticZipInfo(output_path), data) + build_utils.AddToZipHermetic(srcjar, output_path, data=data) else: # TODO(agrieve): Delete this non-srcjar branch once GYP is gone. output_paths = []
diff --git a/build/android/gyp/java_google_api_keys.py b/build/android/gyp/java_google_api_keys.py index 95257d36..62c92cd 100755 --- a/build/android/gyp/java_google_api_keys.py +++ b/build/android/gyp/java_google_api_keys.py
@@ -12,6 +12,8 @@ import sys import zipfile +from util import build_utils + sys.path.append( os.path.abspath(os.path.join(sys.path[0], '../../../google_apis'))) import google_api_keys @@ -23,8 +25,6 @@ PACKAGE = 'org.chromium.chrome' CLASSNAME = 'GoogleAPIKeys' -HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) -HERMETIC_FILE_ATTR = (0644 << 16L) def GetScriptName(): @@ -84,10 +84,8 @@ os.makedirs(folder) with zipfile.ZipFile(output_path, 'w') as srcjar: path = '%s/%s' % (PACKAGE.replace('.', '/'), CLASSNAME + '.java') - zipinfo = zipfile.ZipInfo(filename=path, - date_time=HERMETIC_TIMESTAMP) - zipinfo.external_attr = HERMETIC_FILE_ATTR - srcjar.writestr(zipinfo, GenerateOutput(constant_definition)) + data = GenerateOutput(constant_definition) + build_utils.AddToZipHermetic(srcjar, path, data=data) def _DoMain(argv):
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index 94935d2d..a8eb7c4 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -27,8 +27,8 @@ # aapt should ignore OWNERS files in addition the default ignore pattern. AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' + '!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp') -HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) -HERMETIC_FILE_ATTR = (0644 << 16L) +_HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) +_HERMETIC_FILE_ATTR = (0644 << 16L) @contextlib.contextmanager @@ -224,12 +224,39 @@ z.extract(name, path) -def CreateHermeticZipInfo(zip_path): - """Creates a ZipInfo with a zero'ed out timestamp.""" +def AddToZipHermetic(zip_file, zip_path, src_path=None, data=None, + compress=None): + """Adds a file to the given ZipFile with a hard-coded modified time. + + Args: + zip_file: ZipFile instance to add the file to. + zip_path: Destination path within the zip file. + src_path: Path of the source file. Mutually exclusive with |data|. + data: File data as a string. + compress: Whether to enable compression. Default is take from ZipFile + constructor. + """ + assert (src_path is None) != (data is None), ( + '|src_path| and |data| are mutually exclusive.') CheckZipPath(zip_path) - zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=HERMETIC_TIMESTAMP) - zipinfo.external_attr = HERMETIC_FILE_ATTR - return zipinfo + zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=_HERMETIC_TIMESTAMP) + zipinfo.external_attr = _HERMETIC_FILE_ATTR + + if src_path: + with file(src_path) as f: + data = f.read() + + # zipfile will deflate even when it makes the file bigger. To avoid + # growing files, disable compression at an arbitrary cut off point. + if len(data) < 16: + compress = False + + # None converts to ZIP_STORED, when passed explicitly rather than the + # default passed to the ZipFile constructor. + args = [] + if compress is not None: + args.append(zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED) + zip_file.writestr(zipinfo, data, *args) def DoZip(inputs, output, base_dir=None): @@ -250,9 +277,7 @@ input_tuples.sort(key=lambda tup: tup[0]) with zipfile.ZipFile(output, 'w') as outfile: for zip_path, fs_path in input_tuples: - with file(fs_path) as f: - contents = f.read() - outfile.writestr(CreateHermeticZipInfo(zip_path), contents) + AddToZipHermetic(outfile, zip_path, src_path=fs_path) def ZipDir(output, base_dir): @@ -283,7 +308,7 @@ dst_name = path_transform(name, in_file) already_added = dst_name in added_names if not already_added and not MatchesGlob(dst_name, exclude_patterns): - out_zip.writestr(CreateHermeticZipInfo(dst_name), in_zip.read(name)) + AddToZipHermetic(out_zip, dst_name, data=in_zip.read(name)) added_names.add(dst_name)
diff --git a/build/android/incremental_install/java/org/chromium/incrementalinstall/BootstrapApplication.java b/build/android/incremental_install/java/org/chromium/incrementalinstall/BootstrapApplication.java index e932c1bd..67c60e5 100644 --- a/build/android/incremental_install/java/org/chromium/incrementalinstall/BootstrapApplication.java +++ b/build/android/incremental_install/java/org/chromium/incrementalinstall/BootstrapApplication.java
@@ -74,11 +74,12 @@ LockFile.clearInstallerLock(firstRunLockFile); } - Bundle metadata = getManifestMetadata(); // mInstrumentationAppDir is one of a set of fields that is initialized only when // instrumentation is active. if (Reflect.getField(mActivityThread, "mInstrumentationAppDir") != null) { - initInstrumentation(metadata.getString(REAL_INSTRUMENTATION_META_DATA_NAME)); + String realInstrumentationName = + getClassNameFromMetadata(REAL_INSTRUMENTATION_META_DATA_NAME); + initInstrumentation(realInstrumentationName); } else { Log.i(TAG, "No instrumentation active."); } @@ -92,7 +93,7 @@ // attachBaseContext() is called from ActivityThread#handleBindApplication() and // Application#mApplication is changed right after we return. Thus, we cannot swap // the Application instances until onCreate() is called. - String realApplicationName = metadata.getString(REAL_APP_META_DATA_NAME); + String realApplicationName = getClassNameFromMetadata(REAL_APP_META_DATA_NAME); Log.i(TAG, "Instantiating " + realApplicationName); mRealApplication = (Application) Reflect.newInstance(Class.forName(realApplicationName)); @@ -110,6 +111,20 @@ } /** + * Returns the fully-qualified class name for the given key, stored in a + * <meta> witin the manifest. + */ + private String getClassNameFromMetadata(String key) throws NameNotFoundException { + ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), + PackageManager.GET_META_DATA); + String value = appInfo.metaData.getString(key); + if (!value.contains(".")) { + value = getPackageName() + "." + value; + } + return value; + } + + /** * Instantiates and initializes mRealInstrumentation (the real Instrumentation class). */ private void initInstrumentation(String realInstrumentationName) @@ -163,16 +178,6 @@ } /** - * Returns the class name of the real Application class (recorded in the - * AndroidManifest.xml) - */ - private Bundle getManifestMetadata() throws NameNotFoundException { - ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), - PackageManager.GET_META_DATA); - return appInfo.metaData; - } - - /** * Nulls out ActivityThread.mBoundApplication.providers. */ private void disableContentProviders() throws ReflectiveOperationException {
diff --git a/build/common.gypi b/build/common.gypi index 5c2098b..e498d3eb 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -860,6 +860,7 @@ }], ['OS=="ios"', { + 'configuration_policy%': 0, 'disable_ftp_support%': 1, 'enable_extensions%': 0, 'enable_google_now%': 0,
diff --git a/build/config/android/BUILD.gn b/build/config/android/BUILD.gn index 4cabe11..e6270c3 100644 --- a/build/config/android/BUILD.gn +++ b/build/config/android/BUILD.gn
@@ -42,14 +42,6 @@ } } - if (is_asan) { - # Android build relies on -Wl,--gc-sections removing unreachable code. - # ASan instrumentation for globals inhibits this and results in a library - # with unresolvable relocations. - # TODO(eugenis): find a way to reenable this. - cflags += [ "-mllvm -asan-globals=0" ] - } - # Use gold for Android for most CPU architectures. if (current_cpu == "x86" || current_cpu == "x64" || current_cpu == "arm") { ldflags += [ "-fuse-ld=gold" ]
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 3d91676..2567d863 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/android/config.gni") +import("//build/config/sanitizers/sanitizers.gni") import("//build/config/zip.gni") import("//third_party/ijar/ijar.gni") @@ -667,6 +668,8 @@ # native_lib_placeholders: List of placeholder filenames to add to the apk # (optional). # native_libs_dir: Directory containing native libraries. +# write_asset_list: Adds an extra file to the assets, which contains a list of +# all other asset files. template("package_apk") { action(target_name) { forward_variables_from(invoker, @@ -717,6 +720,9 @@ "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", ] } + if (defined(invoker.write_asset_list) && invoker.write_asset_list) { + args += [ "--write-asset-list" ] + } if (defined(invoker.dex_path)) { _rebased_dex_path = rebase_path(invoker.dex_path, root_build_dir) args += [ "--dex-file=$_rebased_dex_path" ] @@ -1009,6 +1015,7 @@ "emma_instrument", "native_lib_placeholders", "native_libs_dir", + "write_asset_list", ]) deps = _deps + [ ":${_package_resources_target_name}" ] @@ -1971,6 +1978,9 @@ "--num_retries=0", ] } + if (is_asan) { + test_runner_args += [ "--tool=asan" ] + } generated_script = "$root_build_dir/bin/run_${_test_name}" outputs = [
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index e6560704..f3f5e27e 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1201,6 +1201,8 @@ # include_all_resources - If true include all resource IDs in all generated # R.java files. # testonly: Marks this target as "test-only". +# write_asset_list: Adds an extra file to the assets, which contains a list of +# all other asset files. # # DEPRECATED_java_in_dir: Directory containing java files. All .java files in # this directory will be included in the library. This is only supported to @@ -1655,6 +1657,7 @@ "extensions_to_not_compress", "language_splits", "shared_resources", + "write_asset_list", ]) apk_path = _final_apk_path android_manifest = _android_manifest @@ -1912,38 +1915,37 @@ # unittests_dep = ":foo_unittests" # } template("unittest_apk") { - set_sources_assignment_filter([]) - testonly = true - - assert(defined(invoker.unittests_dep), "Need unittests_dep for $target_name") - - test_suite_name = get_label_info(invoker.unittests_dep, "name") - - # This trivial assert is needed in case both unittests_binary and apk_name - # are defined, as otherwise test_suite_name would not be used. - assert(test_suite_name != "") - - if (defined(invoker.unittests_binary)) { - unittests_binary = invoker.unittests_binary - } else { - unittests_binary = "lib${test_suite_name}${shlib_extension}" - } - - if (defined(invoker.apk_name)) { - apk_name = invoker.apk_name - } else { - apk_name = test_suite_name - } - android_apk(target_name) { - forward_variables_from(invoker, - [ - "asset_location", - "android_manifest", - ]) + set_sources_assignment_filter([]) + data_deps = [] + deps = [] + forward_variables_from(invoker, "*") + testonly = true + + assert(defined(unittests_dep), "Need unittests_dep for $target_name") + + test_suite_name = get_label_info(unittests_dep, "name") + + # This trivial assert is needed in case both unittests_binary and apk_name + # are defined, as otherwise test_suite_name would not be used. + assert(test_suite_name != "") + + if (!defined(apk_name)) { + apk_name = test_suite_name + } + + if (!defined(android_manifest)) { + android_manifest = + "//testing/android/native_test/java/AndroidManifest.xml" + } + + if (!defined(unittests_binary)) { + unittests_binary = "lib${test_suite_name}${shlib_extension}" + } + final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk" - if (!defined(invoker.use_default_launcher) || invoker.use_default_launcher) { + if (!defined(use_default_launcher) || use_default_launcher) { java_files = [ "//testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java", "//testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java", @@ -1951,29 +1953,17 @@ "//testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java", ] } - if (!defined(invoker.android_manifest)) { - android_manifest = - "//testing/android/native_test/java/AndroidManifest.xml" - } native_libs = [ unittests_binary ] - deps = [ + deps += [ "//base:base_java", "//build/android/pylib/remote/device/dummy:remote_device_dummy_apk", "//testing/android/appurify_support:appurify_support_java", "//testing/android/reporter:reporter_java", ] - if (defined(invoker.deps)) { - deps += invoker.deps - } - data_deps = [ - "//tools/android/md5sum", - ] + data_deps += [ "//tools/android/md5sum" ] if (host_os == "linux") { data_deps += [ "//tools/android/forwarder2" ] } - if (defined(invoker.data_deps)) { - data_deps += invoker.data_deps - } } }
diff --git a/build/config/features.gni b/build/config/features.gni index 9fb42052..f35f905 100644 --- a/build/config/features.gni +++ b/build/config/features.gni
@@ -63,7 +63,6 @@ # proprietary codecs. proprietary_codecs = is_android || is_chrome_branded || is_chromecast - # TODO(GYP) This should be enabled on ios as well. enable_configuration_policy = !is_ios # Enables support for background apps.
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index 19d0a3ff..c958e2d3 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn
@@ -102,8 +102,21 @@ "-fsanitize=address", "-fsanitize-blacklist=$asan_blacklist_path", ] - if (is_mac) { - cflags += [ "-mllvm -asan-globals=0" ] # http://crbug.com/352073 + if (is_android) { + # Android build relies on -Wl,--gc-sections removing unreachable code. + # ASan instrumentation for globals inhibits this and results in a + # library with unresolvable relocations. + # TODO(eugenis): find a way to reenable this. + cflags += [ + "-mllvm", + "-asan-globals=0", + ] + } else if (is_mac) { + # http://crbug.com/352073 + cflags += [ + "-mllvm", + "-asan-globals=0", + ] # TODO(GYP): deal with mac_bundles. } }
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 69a94db2..ddf28f1 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -85,3 +85,6 @@ assert( !is_debug || !(is_msan || is_lsan || is_tsan || is_ubsan || is_ubsan_vptr), "Sanitizers should generally be used in release (set is_debug=false).") + +assert(!(is_android && is_asan && !is_component_build), + "is_asan on Android requires is_component_build to be set")
diff --git a/build/gdb-add-index b/build/gdb-add-index index 992ac161..8df437f7 100755 --- a/build/gdb-add-index +++ b/build/gdb-add-index
@@ -13,6 +13,17 @@ # When modifying this code, most of the real logic is in the index_one_file # function. The rest is cleanup + sempahore plumbing. +function usage_exit { + echo "Usage: $0 [-f] [-r] [-n] <paths-to-binaries>..." + echo " -f forces replacement of an existing index." + echo " -r removes the index section." + echo " -n don't extract the dependencies of each binary with lld." + echo " e.g., $0 -n out/Debug/lib.unstripped/lib*" + echo + echo " Set TOOLCHAIN_PREFIX to use a non-default set of binutils." + exit 1 +} + # Cleanup temp directory and ensure all child jobs are dead-dead. function on_exit { trap "" EXIT USR1 # Avoid reentrancy. @@ -25,9 +36,9 @@ echo "done" fi - if [ -f "$DIRECTORY" ]; then - echo -n "Removing temp directory $DIRECTORY..." - rm -rf $DIRECTORY + if [ -f "$directory" ]; then + echo -n "Removing temp directory $directory..." + rm -rf "$directory" echo done fi } @@ -36,31 +47,31 @@ function index_one_file { local file=$1 local basename=$(basename "$file") - local should_index="${SHOULD_INDEX}" + local should_index_this_file="${should_index}" local readelf_out=$(${TOOLCHAIN_PREFIX}readelf -S "$file") if [[ $readelf_out =~ "gdb_index" ]]; then - if [ "${REMOVE_INDEX}" = 1 ]; then + if $remove_index; then ${TOOLCHAIN_PREFIX}objcopy --remove-section .gdb_index "$file" echo "Removed index from $basename." else echo "Skipped $basename -- already contains index." - should_index=0 + should_index_this_file=false fi fi - if [ "${should_index}" = 1 ]; then + if $should_index_this_file; then local start=$(date +"%s%N") echo "Adding index to $basename..." - ${TOOLCHAIN_PREFIX}gdb -batch "$file" -ex "save gdb-index $DIRECTORY" \ + ${TOOLCHAIN_PREFIX}gdb -batch "$file" -ex "save gdb-index $directory" \ -ex "quit" - local index_file="$DIRECTORY/$basename.gdb-index" + local index_file="$directory/$basename.gdb-index" if [ -f "$index_file" ]; then ${TOOLCHAIN_PREFIX}objcopy --add-section .gdb_index="$index_file" \ --set-section-flags .gdb_index=readonly "$file" "$file" local finish=$(date +"%s%N") - local elapsed=$(((finish - start)/1000000)) + local elapsed=$(((finish - start) / 1000000)) echo " ...$basename indexed. [${elapsed}ms]" else echo " ...$basename unindexable." @@ -79,75 +90,86 @@ } & } -CUR_FILE_NUM=0 +cur_file_num=0 function index_next { - if (( CUR_FILE_NUM >= ${#FILES_TO_INDEX[@]} )); then + if ((cur_file_num >= ${#files_to_index[@]})); then return fi - async_index "${FILES_TO_INDEX[CUR_FILE_NUM]}" - ((CUR_FILE_NUM += 1)) || true + async_index "${files_to_index[cur_file_num]}" + ((cur_file_num += 1)) || true } - ######## ### Main body of the script. -REMOVE_INDEX=0 -SHOULD_INDEX=1 -while getopts ":f:r" opt; do - case $opt in - f) - REMOVE_INDEX=1 - shift +remove_index=false +should_index=true +should_index_deps=true +files_to_index=() +while (($# > 0)); do + case "$1" in + -h) + usage_exit ;; - r) - REMOVE_INDEX=1 - SHOULD_INDEX=0 - shift + -f) + remove_index=true + ;; + -r) + remove_index=true + should_index=false + ;; + -n) + should_index_deps=false + ;; + -*) + echo "Invalid option: $1" >&2 + usage_exit ;; *) - echo "Invalid option: -$OPTARG" >&2 + if [[ ! -f "$1" ]]; then + echo "Path $1 does not exist." + exit 1 + fi + files_to_index+=("$1") ;; esac + shift done -if [[ ! $# == 1 ]]; then - echo "Usage: $0 [-f] [-r] path-to-binary" - echo " -f forces replacement of an existing index." - echo " -r removes the index section." - exit 1 +if ((${#files_to_index[@]} == 0)); then + usage_exit fi -FILENAME="$1" -if [[ ! -f "$FILENAME" ]]; then - echo "Path $FILENAME does not exist." - exit 1 +dependencies=() +if $should_index_deps; then + for file in "${files_to_index[@]}"; do + # Append the shared library dependencies of this file that + # have the same dirname. The dirname is a signal that these + # shared libraries were part of the same build as the binary. + dependencies+=( \ + $(ldd "$file" 2>/dev/null \ + | grep $(dirname "$file") \ + | sed "s/.*[ \t]\(.*\) (.*/\1/") \ + ) + done fi +files_to_index+=("${dependencies[@]}") # Ensure we cleanup on on exit. -trap on_exit EXIT +trap on_exit EXIT INT # We're good to go! Create temp directory for index files. -DIRECTORY=$(mktemp -d) -echo "Made temp directory $DIRECTORY." - -# Create array with the filename and all shared libraries that -# have the same dirname. The dirname is a signal that these -# shared libraries were part of the same build as the binary. -declare -a FILES_TO_INDEX=($FILENAME - $(ldd "$FILENAME" 2>/dev/null \ - | grep $(dirname "$FILENAME") \ - | sed "s/.*[ \t]\(.*\) (.*/\1/") -) +directory=$(mktemp -d) +echo "Made temp directory $directory." # Start concurrent indexing. trap index_next USR1 # 4 is an arbitrary default. When changing, remember we are likely IO bound # so basing this off the number of cores is not sensible. -INDEX_TASKS=${INDEX_TASKS:-4} -for ((i=0;i<${INDEX_TASKS};i++)); do +index_tasks=${INDEX_TASKS:-4} +for ((i = 0; i < index_tasks; i++)); do index_next done @@ -157,6 +179,6 @@ # an indication that the loop should continue. Unfortunately, it also means # we cannot use set -e since technically the "wait" is failing. wait -while (( $? > 128 )); do +while (($? > 128)); do wait done
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 7c8b1a1..cf7fa7b 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi
@@ -91,7 +91,7 @@ '../ui/accessibility/accessibility.gyp:accessibility_unittests', '../ui/base/ui_base_tests.gyp:ui_base_unittests', '../ui/display/display.gyp:display_unittests', - '../ui/events/events.gyp:events_unittests', + '../ui/events/events_unittests.gyp:events_unittests', '../ui/gfx/gfx_tests.gyp:gfx_unittests', '../ui/gl/gl_tests.gyp:gl_unittests', '../ui/snapshot/snapshot.gyp:snapshot_unittests', @@ -198,6 +198,7 @@ '../content/content_shell_and_tests.gyp:content_junit_tests', '../content/content_shell_and_tests.gyp:content_shell_apk', '../content/content_shell_and_tests.gyp:content_unittests_apk', + '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest_apk', '../device/device_tests.gyp:device_unittests_apk', '../gpu/gpu.gyp:gpu_unittests_apk', '../media/media.gyp:media_unittests_apk', @@ -216,7 +217,7 @@ '../tools/imagediff/image_diff.gyp:image_diff#host', '../tools/telemetry/telemetry.gyp:bitmaptools#host', '../ui/base/ui_base_tests.gyp:ui_base_unittests_apk', - '../ui/events/events.gyp:events_unittests_apk', + '../ui/events/events_unittests.gyp:events_unittests_apk', '../ui/gfx/gfx_tests.gyp:gfx_unittests_apk', '../ui/gl/gl_tests.gyp:gl_unittests_apk', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_apk', @@ -582,7 +583,7 @@ '../ui/accessibility/accessibility.gyp:accessibility_unittests_run', '../ui/app_list/app_list.gyp:app_list_unittests_run', '../ui/compositor/compositor.gyp:compositor_unittests_run', - '../ui/events/events.gyp:events_unittests_run', + '../ui/events/events_unittests.gyp:events_unittests_run', '../ui/message_center/message_center.gyp:message_center_unittests_run', '../url/url.gyp:url_unittests_run', ], @@ -765,7 +766,6 @@ '../components/components.gyp:cronet_perf_test_apk', '../content/content_shell_and_tests.gyp:chromium_linker_test_apk', '../content/content_shell_and_tests.gyp:content_shell_test_apk', - '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest_apk', '../gpu/gpu.gyp:gl_tests_apk', '../gpu/gpu.gyp:gpu_perftests_apk', '../ipc/ipc.gyp:ipc_tests_apk',
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index af3c962..eaca1133 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt
@@ -597,7 +597,6 @@ IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON IDS_PASSWORD_MANAGER_SAVE_BUTTON IDS_PASSWORD_MANAGER_SMART_LOCK -IDS_PASSWORD_MANAGER_SMART_LOCK_PAGE IDS_PAST_TIME_TODAY IDS_PAST_TIME_YESTERDAY IDS_PDF_INFOBAR_ALWAYS_USE_READER_BUTTON
diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc index 342ab94..b06ec7e 100644 --- a/build/sanitizers/sanitizer_options.cc +++ b/build/sanitizers/sanitizer_options.cc
@@ -12,8 +12,9 @@ #include <string.h> #endif // ADDRESS_SANITIZER && OS_MACOSX -#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ - defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) +#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ + defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \ + defined(UNDEFINED_SANITIZER) // Functions returning default options are declared weak in the tools' runtime // libraries. To make the linker pick the strong replacements for those // functions from this module, we explicitly force its inclusion by passing @@ -25,12 +26,10 @@ // aren't referenced from the Chrome executable. We must ensure that those // callbacks are not sanitizer-instrumented, and that they aren't stripped by // the linker. -#define SANITIZER_HOOK_ATTRIBUTE \ - extern "C" \ - __attribute__((no_sanitize_address)) \ - __attribute__((no_sanitize_memory)) \ - __attribute__((no_sanitize_thread)) \ - __attribute__((visibility("default"))) \ +#define SANITIZER_HOOK_ATTRIBUTE \ + extern "C" \ + __attribute__((no_sanitize("address", "memory", "thread", "undefined"))) \ + __attribute__((visibility("default"))) \ __attribute__((used)) #endif @@ -177,3 +176,14 @@ } #endif // LEAK_SANITIZER + +#if defined(UNDEFINED_SANITIZER) +// Default options for UndefinedBehaviorSanitizer: +// print_stacktrace=1 - print the stacktrace when UBSan reports an error. +const char kUbsanDefaultOptions[] = "print_stacktrace=1"; + +SANITIZER_HOOK_ATTRIBUTE const char* __ubsan_default_options() { + return kUbsanDefaultOptions; +} + +#endif // UNDEFINED_SANITIZER
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index cc73daf5..72772c4c 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -239,6 +239,13 @@ // https://code.google.com/p/v8/issues/detail?id=3143 "race:v8::internal::FLAG_track_double_fields\n" +// https://crbug.com/369257 +// TODO(mtklein): annotate properly and remove suppressions. +"race:SandboxIPCHandler::HandleFontMatchRequest\n" +"race:SkFontConfigInterfaceDirect::matchFamilyName\n" +"race:SkFontConfigInterface::GetSingletonDirectInterface\n" +"race:FcStrStaticName\n" + // http://crbug.com/374135 "race:media::AlsaWrapper::PcmWritei\n" @@ -280,6 +287,7 @@ // https://crbug.com/448203 "race:blink::RemoteFrame::detach\n" +// Lock inversion in third party code, won't fix. // https://crbug.com/455638 "deadlock:dbus::Bus::ShutdownAndBlock\n"
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 8fd1828..3e5b0a2 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -313,6 +313,8 @@ "playback/largest_display_item.h", "playback/transform_display_item.cc", "playback/transform_display_item.h", + "proto/cc_conversions.cc", + "proto/cc_conversions.h", "proto/gfx_conversions.cc", "proto/gfx_conversions.h", "proto/skia_conversions.cc", @@ -796,6 +798,7 @@ "playback/display_item_list_unittest.cc", "playback/display_list_raster_source_unittest.cc", "playback/display_list_recording_source_unittest.cc", + "proto/cc_conversions_unittest.cc", "proto/gfx_conversions_unittest.cc", "proto/skia_conversions_unittest.cc", "quads/draw_polygon_unittest.cc",
diff --git a/cc/base/switches.cc b/cc/base/switches.cc index af836e3f..13a9735 100644 --- a/cc/base/switches.cc +++ b/cc/base/switches.cc
@@ -56,10 +56,10 @@ // Enables the GPU benchmarking extension const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking"; -// Disables the use of property trees rather than CalcDrawProps for computing +// Enables the use of property trees rather than CalcDrawProps for computing // draw properties. -const char kDisableCompositorPropertyTrees[] = - "disable-compositor-property-trees"; +const char kEnableCompositorPropertyTrees[] = + "enable-compositor-property-trees"; // Renders a border around compositor layers to help debug and study // layer compositing.
diff --git a/cc/base/switches.h b/cc/base/switches.h index 3465eaf9..bd5b2eb 100644 --- a/cc/base/switches.h +++ b/cc/base/switches.h
@@ -30,7 +30,7 @@ // Switches for both the renderer and ui compositors. CC_EXPORT extern const char kEnableBeginFrameScheduling[]; CC_EXPORT extern const char kEnableGpuBenchmarking[]; -CC_EXPORT extern const char kDisableCompositorPropertyTrees[]; +CC_EXPORT extern const char kEnableCompositorPropertyTrees[]; // Debug visualizations. CC_EXPORT extern const char kShowCompositedLayerBorders[];
diff --git a/cc/blink/web_content_layer_impl.cc b/cc/blink/web_content_layer_impl.cc index 2990978..174054d 100644 --- a/cc/blink/web_content_layer_impl.cc +++ b/cc/blink/web_content_layer_impl.cc
@@ -58,6 +58,10 @@ return layer_.get(); } +gfx::Rect WebContentLayerImpl::PaintableRegion() { + return client_->paintableRegion(); +} + scoped_refptr<cc::DisplayItemList> WebContentLayerImpl::PaintContentsToDisplayList( const gfx::Rect& clip,
diff --git a/cc/blink/web_content_layer_impl.h b/cc/blink/web_content_layer_impl.h index 79b61d8..228e6ef 100644 --- a/cc/blink/web_content_layer_impl.h +++ b/cc/blink/web_content_layer_impl.h
@@ -34,6 +34,7 @@ ~WebContentLayerImpl() override; // ContentLayerClient implementation. + gfx::Rect PaintableRegion() override; scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting painting_control) override;
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc index 726cfa6..bde0bdf1 100644 --- a/cc/blink/web_layer_impl.cc +++ b/cc/blink/web_layer_impl.cc
@@ -25,8 +25,6 @@ #include "cc/trees/layer_tree_host.h" #include "third_party/WebKit/public/platform/WebFloatPoint.h" #include "third_party/WebKit/public/platform/WebFloatRect.h" -#include "third_party/WebKit/public/platform/WebGraphicsLayerDebugInfo.h" -#include "third_party/WebKit/public/platform/WebLayerClient.h" #include "third_party/WebKit/public/platform/WebLayerPositionConstraint.h" #include "third_party/WebKit/public/platform/WebLayerScrollClient.h" #include "third_party/WebKit/public/platform/WebSize.h" @@ -54,20 +52,15 @@ WebLayerImpl::WebLayerImpl() : layer_(Layer::Create(LayerSettings())), contents_opaque_is_fixed_(false) { - web_layer_client_ = nullptr; - layer_->SetLayerClient(this); } WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer) : layer_(layer), contents_opaque_is_fixed_(false) { - web_layer_client_ = nullptr; - layer_->SetLayerClient(this); } WebLayerImpl::~WebLayerImpl() { if (animation_delegate_adapter_.get()) layer_->set_layer_animation_delegate(nullptr); - web_layer_client_ = nullptr; layer_->SetLayerClient(nullptr); } @@ -493,39 +486,12 @@ return !layer_->layer_tree_host(); } -void WebLayerImpl::setWebLayerClient(blink::WebLayerClient* client) { - web_layer_client_ = client; +void WebLayerImpl::setLayerClient(cc::LayerClient* client) { + layer_->SetLayerClient(client); } -class TracedDebugInfo : public base::trace_event::ConvertableToTraceFormat { - public: - // This object takes ownership of the debug_info object. - explicit TracedDebugInfo(blink::WebGraphicsLayerDebugInfo* debug_info) - : debug_info_(debug_info) {} - void AppendAsTraceFormat(std::string* out) const override { - DCHECK(thread_checker_.CalledOnValidThread()); - blink::WebString web_string; - debug_info_->appendAsTraceFormat(&web_string); - out->append(web_string.utf8()); - } - - private: - ~TracedDebugInfo() override {} - scoped_ptr<blink::WebGraphicsLayerDebugInfo> debug_info_; - base::ThreadChecker thread_checker_; -}; - -scoped_refptr<base::trace_event::ConvertableToTraceFormat> -WebLayerImpl::TakeDebugInfo() { - if (!web_layer_client_) - return nullptr; - blink::WebGraphicsLayerDebugInfo* debug_info = - web_layer_client_->takeDebugInfoFor(this); - - if (debug_info) - return new TracedDebugInfo(debug_info); - else - return nullptr; +const cc::Layer* WebLayerImpl::ccLayer() const { + return layer_.get(); } void WebLayerImpl::setScrollParent(blink::WebLayer* parent) {
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h index e9f79c0..eb5be7ed 100644 --- a/cc/blink/web_layer_impl.h +++ b/cc/blink/web_layer_impl.h
@@ -27,7 +27,6 @@ namespace blink { class WebFilterOperations; -class WebLayerClient; struct WebFloatRect; } @@ -46,7 +45,7 @@ class WebToCCAnimationDelegateAdapter; -class WebLayerImpl : public blink::WebLayer, public cc::LayerClient { +class WebLayerImpl : public blink::WebLayer { public: CC_BLINK_EXPORT WebLayerImpl(); CC_BLINK_EXPORT explicit WebLayerImpl(scoped_refptr<cc::Layer>); @@ -146,18 +145,14 @@ blink::WebLayerPositionConstraint positionConstraint() const override; void setScrollClient(blink::WebLayerScrollClient* client) override; bool isOrphan() const override; - void setWebLayerClient(blink::WebLayerClient* client) override; - - // LayerClient implementation. - scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo() - override; + void setLayerClient(cc::LayerClient* client) override; + const cc::Layer* ccLayer() const override; void setScrollParent(blink::WebLayer* parent) override; void setClipParent(blink::WebLayer* parent) override; protected: scoped_refptr<cc::Layer> layer_; - blink::WebLayerClient* web_layer_client_; bool contents_opaque_is_fixed_;
diff --git a/cc/cc.gyp b/cc/cc.gyp index cf12888..8205cb75 100644 --- a/cc/cc.gyp +++ b/cc/cc.gyp
@@ -373,6 +373,8 @@ 'playback/largest_display_item.h', 'playback/transform_display_item.cc', 'playback/transform_display_item.h', + 'proto/cc_conversions.cc', + 'proto/cc_conversions.h', 'proto/gfx_conversions.cc', 'proto/gfx_conversions.h', 'proto/skia_conversions.cc', @@ -594,6 +596,7 @@ 'proto/pointf.proto', 'proto/rect.proto', 'proto/rectf.proto', + 'proto/region.proto', 'proto/scroll_offset.proto', 'proto/size.proto', 'proto/sizef.proto',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 8c45b8df..b5fe7b8 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp
@@ -84,6 +84,7 @@ 'playback/display_item_list_unittest.cc', 'playback/display_list_raster_source_unittest.cc', 'playback/display_list_recording_source_unittest.cc', + 'proto/cc_conversions_unittest.cc', 'proto/gfx_conversions_unittest.cc', 'proto/skia_conversions_unittest.cc', 'quads/draw_polygon_unittest.cc',
diff --git a/cc/layers/content_layer_client.h b/cc/layers/content_layer_client.h index d56ab6e..be00f3f0 100644 --- a/cc/layers/content_layer_client.h +++ b/cc/layers/content_layer_client.h
@@ -23,6 +23,8 @@ DISPLAY_LIST_PAINTING_DISABLED }; + virtual gfx::Rect PaintableRegion() = 0; + virtual scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting painting_status) = 0;
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index b5ba909..4d65a817 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -20,9 +20,9 @@ #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "skia/ext/platform_canvas.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" #include "third_party/skia/include/effects/SkGradientShader.h" @@ -174,7 +174,7 @@ SkISize canvas_size; if (hud_surface_) - canvas_size = hud_surface_->getCanvas()->getDeviceSize(); + canvas_size = hud_surface_->getCanvas()->getBaseLayerSize(); else canvas_size.set(0, 0);
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 68b34dff..d6b1fb019 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -1531,7 +1531,7 @@ scoped_refptr<base::trace_event::ConvertableToTraceFormat> Layer::TakeDebugInfo() { if (client_) - return client_->TakeDebugInfo(); + return client_->TakeDebugInfo(this); else return nullptr; }
diff --git a/cc/layers/layer_client.h b/cc/layers/layer_client.h index bcdf1c3..524399d0 100644 --- a/cc/layers/layer_client.h +++ b/cc/layers/layer_client.h
@@ -5,8 +5,6 @@ #ifndef CC_LAYERS_LAYER_CLIENT_H_ #define CC_LAYERS_LAYER_CLIENT_H_ -#include <string> - #include "base/memory/ref_counted.h" #include "cc/base/cc_export.h" @@ -18,14 +16,19 @@ namespace cc { +class Layer; + class CC_EXPORT LayerClient { public: // Returns a pointer to a debug info object, if one has been computed. // If not, returns nullptr. // If the returned pointer is non-nullptr, the caller takes // ownership of the pointer. + // + // A pointer to the layer is provided for the convenience of layer clients + // which service multiple layers. virtual scoped_refptr<base::trace_event::ConvertableToTraceFormat> - TakeDebugInfo() = 0; + TakeDebugInfo(Layer* layer) = 0; protected: virtual ~LayerClient() {}
diff --git a/cc/layers/picture_image_layer.cc b/cc/layers/picture_image_layer.cc index 357190b..c407862 100644 --- a/cc/layers/picture_image_layer.cc +++ b/cc/layers/picture_image_layer.cc
@@ -49,6 +49,10 @@ SetNeedsDisplay(); } +gfx::Rect PictureImageLayer::PaintableRegion() { + return gfx::Rect(bounds()); +} + scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList( const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) {
diff --git a/cc/layers/picture_image_layer.h b/cc/layers/picture_image_layer.h index a283c45..cb48c96 100644 --- a/cc/layers/picture_image_layer.h +++ b/cc/layers/picture_image_layer.h
@@ -24,6 +24,8 @@ // Layer implementation. scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; + gfx::Rect PaintableRegion() override; + // ContentLayerClient implementation. scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip,
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index 52559de2..ce8184b 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc
@@ -132,11 +132,14 @@ devtools_instrumentation::ScopedLayerTreeTask update_layer( devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id()); - // Calling paint in WebKit can sometimes cause invalidations, so save + // Calling paint in Blink can sometimes cause invalidations, so save // off the invalidation prior to calling update. + // TODO(chrishtr): Blink should no longer be invalidating during paint. + // Try to remove this code. pending_invalidation_.Swap(&recording_invalidation_); pending_invalidation_.Clear(); + // TODO(chrishtr): implement this for synchronized paint. if (layer_tree_host()->settings().record_full_layer) { // Workaround for http://crbug.com/235910 - to retain backwards compat // the full page content must always be provided in the picture layer.
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index bbb2fb21..a2a1312eb 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -415,6 +415,7 @@ // Create an active recording source, but make sure it's not solid. scoped_ptr<FakeDisplayListRecordingSource> active_recording_source = FakeDisplayListRecordingSource::CreateFilledRecordingSource(layer_size); + active_recording_source->SetLayerBounds(layer_size); active_recording_source->add_draw_rect(gfx::Rect(layer_size)); active_recording_source->add_draw_rect( gfx::Rect(0, 0, layer_size.width() - 1, layer_size.height() - 1)); @@ -4495,6 +4496,7 @@ gfx::Rect layer_rect(layer_bounds); FakeContentLayerClient client; + client.set_bounds(layer_bounds); scoped_refptr<PictureLayer> layer = PictureLayer::Create(layer_settings_, &client); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); @@ -4559,6 +4561,7 @@ gfx::Rect layer_rect(layer_bounds); FakeContentLayerClient client; + client.set_bounds(layer_bounds); scoped_refptr<PictureLayer> layer = PictureLayer::Create(layer_settings_, &client); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc index ce1cb3d..950f9d0 100644 --- a/cc/layers/picture_layer_unittest.cc +++ b/cc/layers/picture_layer_unittest.cc
@@ -24,6 +24,7 @@ class MockContentLayerClient : public ContentLayerClient { public: + gfx::Rect PaintableRegion() override { return gfx::Rect(); } scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override {
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index b333b79..cce8cd0 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc
@@ -128,7 +128,7 @@ if (!current_canvas_) return; is_scissor_enabled_ = false; - SkISize size = current_canvas_->getDeviceSize(); + SkISize size = current_canvas_->getBaseLayerSize(); SetClipRect(gfx::Rect(size.width(), size.height())); }
diff --git a/cc/playback/clip_path_display_item.cc b/cc/playback/clip_path_display_item.cc index 3b46621..a5037a2 100644 --- a/cc/playback/clip_path_display_item.cc +++ b/cc/playback/clip_path_display_item.cc
@@ -41,9 +41,9 @@ // Just use skia's serialization method for the SkPath for now. size_t path_size = clip_path_.writeToMemory(nullptr); if (path_size > 0) { - scoped_ptr<char[]> buffer(new char[path_size]); + scoped_ptr<uint8_t[]> buffer(new uint8_t[path_size]); clip_path_.writeToMemory(buffer.get()); - details->set_clip_path(std::string(buffer.get(), path_size)); + details->set_clip_path(buffer.get(), path_size); } } @@ -56,7 +56,7 @@ SkPath clip_path; if (details.has_clip_path()) { - size_t bytes_read = clip_path.readFromMemory(details.clip_path().c_str(), + size_t bytes_read = clip_path.readFromMemory(details.clip_path().data(), details.clip_path().size()); DCHECK_EQ(details.clip_path().size(), bytes_read); }
diff --git a/cc/playback/discardable_image_map_unittest.cc b/cc/playback/discardable_image_map_unittest.cc index 9797a2f..f68b6963 100644 --- a/cc/playback/discardable_image_map_unittest.cc +++ b/cc/playback/discardable_image_map_unittest.cc
@@ -56,6 +56,7 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectTest) { gfx::Rect visible_rect(2048, 2048); FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(visible_rect.size()); // Discardable pixel refs are found in the following grids: // |---|---|---|---| @@ -132,6 +133,7 @@ // Make sure visible rect fits into the layer size. gfx::Size layer_size(visible_rect.right(), visible_rect.bottom()); FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(layer_size); // Discardable pixel refs are found in the following grids: // |---|---|---|---| @@ -158,7 +160,6 @@ FakeDisplayListRecordingSource recording_source; Region invalidation(visible_rect); - recording_source.set_pixel_record_distance(0); recording_source.SetGenerateDiscardableImagesMetadata(true); recording_source.UpdateAndExpandInvalidation( &content_layer_client, &invalidation, layer_size, visible_rect, 1, @@ -232,6 +233,7 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectOnePixelQuery) { gfx::Rect visible_rect(2048, 2048); FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(visible_rect.size()); // Discardable pixel refs are found in the following grids: // |---|---|---|---| @@ -291,6 +293,7 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectMassiveImage) { gfx::Rect visible_rect(2048, 2048); FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(visible_rect.size()); skia::RefPtr<SkImage> discardable_image; discardable_image = CreateDiscardableImage(gfx::Size(1 << 25, 1 << 25));
diff --git a/cc/playback/display_list_recording_source.cc b/cc/playback/display_list_recording_source.cc index 3a30cf9..603bbde 100644 --- a/cc/playback/display_list_recording_source.cc +++ b/cc/playback/display_list_recording_source.cc
@@ -16,17 +16,6 @@ namespace { -// Layout pixel buffer around the visible layer rect to record. Any base -// picture that intersects the visible layer rect expanded by this distance -// will be recorded. -const int kPixelDistanceToRecord = 4000; - -// This is the distance, in layer space, by which the recorded viewport has to -// change before causing a paint of the new content. For example, it means -// that one has to scroll a very large page by 512 pixels before we will -// re-record a new DisplayItemList for an updated recorded viewport. -const int kMinimumDistanceBeforeUpdatingRecordedViewport = 512; - #ifdef NDEBUG const bool kDefaultClearCanvasSetting = false; #else @@ -50,58 +39,23 @@ clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), solid_color_(SK_ColorTRANSPARENT), background_color_(SK_ColorTRANSPARENT), - pixel_record_distance_(kPixelDistanceToRecord), painter_reported_memory_usage_(0) {} DisplayListRecordingSource::~DisplayListRecordingSource() { } -// This method only really makes sense to call if the size of the layer didn't -// change. -bool DisplayListRecordingSource::ExposesEnoughNewArea( - const gfx::Rect& current_recorded_viewport, - const gfx::Rect& potential_new_recorded_viewport, - const gfx::Size& layer_size) { - // If both are empty, nothing to do. - if (current_recorded_viewport.IsEmpty() && - potential_new_recorded_viewport.IsEmpty()) - return false; +void DisplayListRecordingSource::UpdateInvalidationForNewViewport( + const gfx::Rect& old_recorded_viewport, + const gfx::Rect& new_recorded_viewport, + Region* invalidation) { + // Invalidate newly-exposed and no-longer-exposed areas. + Region newly_exposed_region(new_recorded_viewport); + newly_exposed_region.Subtract(old_recorded_viewport); + invalidation->Union(newly_exposed_region); - // Re-record when going from empty to not-empty, to cover cases where - // the layer is recorded for the first time, or otherwise becomes visible. - if (current_recorded_viewport.IsEmpty()) - return true; - - // Re-record if the new viewport includes area outside of a skirt around the - // existing viewport. - gfx::Rect expanded_viewport(current_recorded_viewport); - expanded_viewport.Inset(-kMinimumDistanceBeforeUpdatingRecordedViewport, - -kMinimumDistanceBeforeUpdatingRecordedViewport); - if (!expanded_viewport.Contains(potential_new_recorded_viewport)) - return true; - - // Even if the new viewport doesn't include enough new area to satisfy the - // condition above, re-record anyway if touches a layer edge not touched by - // the existing viewport. Viewports are clipped to layer boundaries, so if the - // new viewport touches a layer edge not touched by the existing viewport, - // the new viewport must expose new area that touches this layer edge. Since - // this new area touches a layer edge, it's impossible to expose more area in - // that direction, so recording cannot be deferred until the exposed new area - // satisfies the condition above. - if (potential_new_recorded_viewport.x() == 0 && - current_recorded_viewport.x() != 0) - return true; - if (potential_new_recorded_viewport.y() == 0 && - current_recorded_viewport.y() != 0) - return true; - if (potential_new_recorded_viewport.right() == layer_size.width() && - current_recorded_viewport.right() != layer_size.width()) - return true; - if (potential_new_recorded_viewport.bottom() == layer_size.height() && - current_recorded_viewport.bottom() != layer_size.height()) - return true; - - return false; + Region no_longer_exposed_region(old_recorded_viewport); + no_longer_exposed_region.Subtract(new_recorded_viewport); + invalidation->Union(no_longer_exposed_region); } bool DisplayListRecordingSource::UpdateAndExpandInvalidation( @@ -114,34 +68,17 @@ ScopedDisplayListRecordingSourceUpdateTimer timer; bool updated = false; + // TODO(chrishtr): delete this conditional once synchronized paint launches. if (size_ != layer_size) { size_ = layer_size; updated = true; } - // The recorded viewport is the visible layer rect, expanded - // by the pixel record distance, up to a maximum of the total - // layer size. - gfx::Rect potential_new_recorded_viewport = visible_layer_rect; - potential_new_recorded_viewport.Inset(-pixel_record_distance_, - -pixel_record_distance_); - potential_new_recorded_viewport.Intersect(gfx::Rect(GetSize())); - - if (updated || - ExposesEnoughNewArea(recorded_viewport_, potential_new_recorded_viewport, - GetSize())) { - gfx::Rect old_recorded_viewport = recorded_viewport_; - recorded_viewport_ = potential_new_recorded_viewport; - - // Invalidate newly-exposed and no-longer-exposed areas. - Region newly_exposed_region(recorded_viewport_); - newly_exposed_region.Subtract(old_recorded_viewport); - invalidation->Union(newly_exposed_region); - - Region no_longer_exposed_region(old_recorded_viewport); - no_longer_exposed_region.Subtract(recorded_viewport_); - invalidation->Union(no_longer_exposed_region); - + gfx::Rect new_recorded_viewport = painter->PaintableRegion(); + if (new_recorded_viewport != recorded_viewport_) { + UpdateInvalidationForNewViewport(recorded_viewport_, new_recorded_viewport, + invalidation); + recorded_viewport_ = new_recorded_viewport; updated = true; }
diff --git a/cc/playback/display_list_recording_source.h b/cc/playback/display_list_recording_source.h index 4a19cbe..603924f 100644 --- a/cc/playback/display_list_recording_source.h +++ b/cc/playback/display_list_recording_source.h
@@ -52,13 +52,6 @@ bool can_use_lcd_text) const; virtual bool IsSuitableForGpuRasterization() const; - // Returns true if the new recorded viewport exposes enough new area to be - // worth re-recording. - static bool ExposesEnoughNewArea( - const gfx::Rect& current_recorded_viewport, - const gfx::Rect& potential_new_recorded_viewport, - const gfx::Size& layer_size); - gfx::Rect recorded_viewport() const { return recorded_viewport_; } protected: @@ -73,12 +66,15 @@ bool clear_canvas_with_debug_color_; SkColor solid_color_; SkColor background_color_; - int pixel_record_distance_; scoped_refptr<DisplayItemList> display_list_; size_t painter_reported_memory_usage_; private: + void UpdateInvalidationForNewViewport(const gfx::Rect& old_recorded_viewport, + const gfx::Rect& new_recorded_viewport, + Region* invalidation); + friend class DisplayListRasterSource; void DetermineIfSolidColor();
diff --git a/cc/playback/display_list_recording_source_unittest.cc b/cc/playback/display_list_recording_source_unittest.cc index cb9b573e6..7b4e24d 100644 --- a/cc/playback/display_list_recording_source_unittest.cc +++ b/cc/playback/display_list_recording_source_unittest.cc
@@ -121,137 +121,6 @@ } } -TEST(DisplayListRecordingSourceTest, ExposesEnoughNewAreaEmpty) { - gfx::Size layer_size(1000, 1000); - - // Both empty means there is nothing to do. - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - gfx::Rect(), gfx::Rect(), layer_size)); - // Going from empty to non-empty means we must re-record because it could be - // the first frame after construction or Clear. - EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( - gfx::Rect(), gfx::Rect(1, 1), layer_size)); - - // Going from non-empty to empty is not special-cased. - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - gfx::Rect(1, 1), gfx::Rect(), layer_size)); -} - -TEST(DisplayListRecordingSourceTest, ExposesEnoughNewAreaNotBigEnough) { - gfx::Size layer_size(1000, 1000); - gfx::Rect current_recorded_viewport(100, 100, 100, 100); - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, gfx::Rect(100, 100, 90, 90), layer_size)); - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, gfx::Rect(100, 100, 100, 100), layer_size)); - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, gfx::Rect(1, 1, 200, 200), layer_size)); -} - -TEST(DisplayListRecordingSourceTest, - ExposesEnoughNewAreaNotBigEnoughButNewAreaTouchesEdge) { - gfx::Size layer_size(500, 500); - gfx::Rect current_recorded_viewport(100, 100, 100, 100); - - // Top edge. - EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, gfx::Rect(100, 0, 100, 200), layer_size)); - - // Left edge. - EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, gfx::Rect(0, 100, 200, 100), layer_size)); - - // Bottom edge. - EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, gfx::Rect(100, 100, 100, 400), layer_size)); - - // Right edge. - EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, gfx::Rect(100, 100, 400, 100), layer_size)); -} - -// Verifies that having a current viewport that touches a layer edge does not -// force re-recording. -TEST(DisplayListRecordingSourceTest, - ExposesEnoughNewAreaCurrentViewportTouchesEdge) { - gfx::Size layer_size(500, 500); - gfx::Rect potential_new_viewport(100, 100, 300, 300); - - // Top edge. - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - gfx::Rect(100, 0, 100, 100), potential_new_viewport, layer_size)); - - // Left edge. - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - gfx::Rect(0, 100, 100, 100), potential_new_viewport, layer_size)); - - // Bottom edge. - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - gfx::Rect(300, 400, 100, 100), potential_new_viewport, layer_size)); - - // Right edge. - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - gfx::Rect(400, 300, 100, 100), potential_new_viewport, layer_size)); -} - -TEST(DisplayListRecordingSourceTest, ExposesEnoughNewAreaScrollScenarios) { - gfx::Size layer_size(1000, 1000); - gfx::Rect current_recorded_viewport(100, 100, 100, 100); - - gfx::Rect new_recorded_viewport(current_recorded_viewport); - new_recorded_viewport.Offset(512, 0); - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, new_recorded_viewport, layer_size)); - new_recorded_viewport.Offset(0, 512); - EXPECT_FALSE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, new_recorded_viewport, layer_size)); - - new_recorded_viewport.Offset(1, 0); - EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, new_recorded_viewport, layer_size)); - - new_recorded_viewport.Offset(-1, 1); - EXPECT_TRUE(DisplayListRecordingSource::ExposesEnoughNewArea( - current_recorded_viewport, new_recorded_viewport, layer_size)); -} - -// Verifies that UpdateAndExpandInvalidation calls ExposesEnoughNewArea with the -// right arguments. -TEST(DisplayListRecordingSourceTest, - ExposesEnoughNewAreaCalledWithCorrectArguments) { - DisplayListRecordingSource recording_source; - FakeContentLayerClient client; - Region invalidation; - gfx::Size layer_size(9000, 9000); - gfx::Rect visible_rect(0, 0, 256, 256); - - recording_source.UpdateAndExpandInvalidation( - &client, &invalidation, layer_size, visible_rect, 0, - DisplayListRecordingSource::RECORD_NORMALLY); - EXPECT_EQ(gfx::Rect(0, 0, 4256, 4256), recording_source.recorded_viewport()); - - visible_rect.Offset(0, 512); - recording_source.UpdateAndExpandInvalidation( - &client, &invalidation, layer_size, visible_rect, 0, - DisplayListRecordingSource::RECORD_NORMALLY); - EXPECT_EQ(gfx::Rect(0, 0, 4256, 4256), recording_source.recorded_viewport()); - - // Move past the threshold for enough exposed new area. - visible_rect.Offset(0, 1); - recording_source.UpdateAndExpandInvalidation( - &client, &invalidation, layer_size, visible_rect, 0, - DisplayListRecordingSource::RECORD_NORMALLY); - EXPECT_EQ(gfx::Rect(0, 0, 4256, 4769), recording_source.recorded_viewport()); - - // Make the bottom of the potential new recorded viewport coincide with the - // layer's bottom edge. - visible_rect.Offset(0, 231); - recording_source.UpdateAndExpandInvalidation( - &client, &invalidation, layer_size, visible_rect, 0, - DisplayListRecordingSource::RECORD_NORMALLY); - EXPECT_EQ(gfx::Rect(0, 0, 4256, 4769), recording_source.recorded_viewport()); -} - TEST(DisplayListRecordingSourceTest, NoGatherImageEmptyImages) { gfx::Rect recorded_viewport(0, 0, 256, 256);
diff --git a/cc/proto/BUILD.gn b/cc/proto/BUILD.gn index 33e3e58..07258a6 100644 --- a/cc/proto/BUILD.gn +++ b/cc/proto/BUILD.gn
@@ -38,6 +38,7 @@ "pointf.proto", "rect.proto", "rectf.proto", + "region.proto", "scroll_offset.proto", "size.proto", "sizef.proto",
diff --git a/cc/proto/cc_conversions.cc b/cc/proto/cc_conversions.cc new file mode 100644 index 0000000..7e466f37 --- /dev/null +++ b/cc/proto/cc_conversions.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 "cc/proto/cc_conversions.h" + +#include "cc/base/region.h" +#include "cc/proto/gfx_conversions.h" +#include "cc/proto/region.pb.h" + +namespace cc { + +void RegionToProto(const Region& region, proto::Region* proto) { + for (Region::Iterator it(region); it.has_rect(); it.next()) + RectToProto(it.rect(), proto->add_rects()); +} + +Region RegionFromProto(const proto::Region& proto) { + Region region; + for (int i = 0; i < proto.rects_size(); ++i) + region.Union(ProtoToRect(proto.rects(i))); + return region; +} + +} // namespace cc
diff --git a/cc/proto/cc_conversions.h b/cc/proto/cc_conversions.h new file mode 100644 index 0000000..4060e6f --- /dev/null +++ b/cc/proto/cc_conversions.h
@@ -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. + +#ifndef CC_PROTO_CC_CONVERSIONS_H_ +#define CC_PROTO_CC_CONVERSIONS_H_ + +#include "cc/base/cc_export.h" + +namespace cc { +class Region; + +namespace proto { +class Region; +} // namespace proto + +// TODO(dtrainor): Move these to a class and make them static +// (crbug.com/548432). +CC_EXPORT void RegionToProto(const Region& region, proto::Region* proto); +CC_EXPORT Region RegionFromProto(const proto::Region& proto); + +} // namespace cc + +#endif // CC_PROTO_CC_CONVERSIONS_H_
diff --git a/cc/proto/cc_conversions_unittest.cc b/cc/proto/cc_conversions_unittest.cc new file mode 100644 index 0000000..8612dda --- /dev/null +++ b/cc/proto/cc_conversions_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 "cc/proto/cc_conversions.h" + +#include "cc/base/region.h" +#include "cc/proto/region.pb.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/rect.h" + +namespace cc { +namespace { + +void VerifySerializeAndDeserializeProto(const Region& region1) { + proto::Region proto; + RegionToProto(region1, &proto); + Region region2 = RegionFromProto(proto); + EXPECT_EQ(region1, region2); +} + +TEST(RegionTest, SingleRectProtoConversion) { + Region region(gfx::Rect(14, 15, 16, 17)); + VerifySerializeAndDeserializeProto(region); +} + +TEST(RegionTest, MultipleRectProtoConversion) { + Region region(gfx::Rect(0, 0, 1, 1)); + region.Union(gfx::Rect(9, 0, 1, 1)); + region.Union(gfx::Rect(0, 9, 1, 1)); + region.Union(gfx::Rect(9, 9, 1, 1)); + VerifySerializeAndDeserializeProto(region); +} + +TEST(RegionTest, OverlappingRectIntersectProtoConversion) { + Region region(gfx::Rect(0, 0, 10, 10)); + region.Intersect(gfx::Rect(5, 5, 10, 10)); + VerifySerializeAndDeserializeProto(region); +} + +TEST(RegionTest, OverlappingRectUnionProtoConversion) { + Region region(gfx::Rect(0, 0, 10, 10)); + region.Union(gfx::Rect(5, 5, 10, 10)); + VerifySerializeAndDeserializeProto(region); +} + +TEST(RegionTest, OverlappingRectSubtractProtoConversion) { + Region region(gfx::Rect(0, 0, 10, 10)); + region.Subtract(gfx::Rect(5, 5, 1, 1)); + VerifySerializeAndDeserializeProto(region); +} + +} // namespace +} // namespace cc
diff --git a/cc/proto/region.proto b/cc/proto/region.proto new file mode 100644 index 0000000..a4d235b --- /dev/null +++ b/cc/proto/region.proto
@@ -0,0 +1,15 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +import "rect.proto"; + +option optimize_for = LITE_RUNTIME; + +package cc.proto; + +message Region { + repeated Rect rects = 1; +}
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index ddf71cf..778ddbe8 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc
@@ -106,7 +106,7 @@ continue; // Transfer resource to |in_use_resources_|. - in_use_resources_.set(resource->id(), it->Pass()); + in_use_resources_[resource->id()] = std::move(*it); unused_resources_.erase(it); in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>( resource->size(), resource->format()); @@ -130,7 +130,7 @@ ++total_resource_count_; Resource* resource = pool_resource.get(); - in_use_resources_.set(resource->id(), std::move(pool_resource)); + in_use_resources_[resource->id()] = std::move(pool_resource); in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>( resource->size(), resource->format()); return resource; @@ -151,7 +151,7 @@ DCHECK(resource_provider_->CanLockForWrite(resource->id())); // Transfer resource to |in_use_resources_|. - in_use_resources_.set(resource->id(), it->Pass()); + in_use_resources_[resource->id()] = std::move(*it); unused_resources_.erase(it); in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>( resource->size(), resource->format()); @@ -162,12 +162,13 @@ auto it = in_use_resources_.find(resource->id()); DCHECK(it != in_use_resources_.end()); - PoolResource* pool_resource = it->second; + PoolResource* pool_resource = it->second.get(); pool_resource->set_content_id(content_id); pool_resource->set_last_usage(base::TimeTicks::Now()); // Transfer resource to |busy_resources_|. - busy_resources_.push_front(in_use_resources_.take_and_erase(it)); + busy_resources_.push_front(std::move(it->second)); + in_use_resources_.erase(it); in_use_memory_usage_bytes_ -= ResourceUtil::UncheckedSizeInBytes<size_t>( pool_resource->size(), pool_resource->format());
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h index e5a21669..e17032b 100644 --- a/cc/resources/resource_pool.h +++ b/cc/resources/resource_pool.h
@@ -6,8 +6,8 @@ #define CC_RESOURCES_RESOURCE_POOL_H_ #include <deque> +#include <map> -#include "base/containers/scoped_ptr_map.h" #include "base/memory/scoped_ptr.h" #include "base/trace_event/memory_dump_provider.h" #include "cc/base/cc_export.h" @@ -120,8 +120,7 @@ ResourceDeque unused_resources_; ResourceDeque busy_resources_; - using ResourceMap = base::ScopedPtrMap<ResourceId, scoped_ptr<PoolResource>>; - ResourceMap in_use_resources_; + std::map<ResourceId, scoped_ptr<PoolResource>> in_use_resources_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; bool evict_expired_resources_pending_;
diff --git a/cc/test/data/background_filter_on_scaled_layer_gl.png b/cc/test/data/background_filter_on_scaled_layer_gl.png index fc5c8f9c..83cb2c5 100644 --- a/cc/test/data/background_filter_on_scaled_layer_gl.png +++ b/cc/test/data/background_filter_on_scaled_layer_gl.png Binary files differ
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc index 0238498d..553bf658 100644 --- a/cc/test/fake_content_layer_client.cc +++ b/cc/test/fake_content_layer_client.cc
@@ -35,6 +35,11 @@ FakeContentLayerClient::~FakeContentLayerClient() { } +gfx::Rect FakeContentLayerClient::PaintableRegion() { + CHECK(bounds_set_); + return gfx::Rect(bounds_); +} + scoped_refptr<DisplayItemList> FakeContentLayerClient::PaintContentsToDisplayList( const gfx::Rect& clip,
diff --git a/cc/test/fake_content_layer_client.h b/cc/test/fake_content_layer_client.h index e24fee7e..a73cfa38 100644 --- a/cc/test/fake_content_layer_client.h +++ b/cc/test/fake_content_layer_client.h
@@ -38,6 +38,7 @@ FakeContentLayerClient(); ~FakeContentLayerClient() override; + gfx::Rect PaintableRegion() override; scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting painting_control) override; @@ -80,6 +81,11 @@ reported_memory_usage_ = reported_memory_usage; } + void set_bounds(gfx::Size bounds) { + bounds_ = bounds; + bounds_set_ = true; + } + private: typedef std::vector<std::pair<gfx::RectF, SkPaint>> RectPaintVector; typedef std::vector<ImageData> ImageVector; @@ -90,6 +96,8 @@ SkCanvas* last_canvas_; PaintingControlSetting last_painting_control_; size_t reported_memory_usage_; + gfx::Size bounds_; + bool bounds_set_; }; } // namespace cc
diff --git a/cc/test/fake_display_list_recording_source.cc b/cc/test/fake_display_list_recording_source.cc index 9f792c7..c48859e 100644 --- a/cc/test/fake_display_list_recording_source.cc +++ b/cc/test/fake_display_list_recording_source.cc
@@ -8,6 +8,10 @@ namespace cc { +FakeDisplayListRecordingSource::FakeDisplayListRecordingSource() + : force_unsuitable_for_gpu_rasterization_(false), + playback_allowed_event_(nullptr) {} + bool FakeDisplayListRecordingSource::IsSuitableForGpuRasterization() const { if (force_unsuitable_for_gpu_rasterization_) return false;
diff --git a/cc/test/fake_display_list_recording_source.h b/cc/test/fake_display_list_recording_source.h index 8b6436c3..f8e3cc17 100644 --- a/cc/test/fake_display_list_recording_source.h +++ b/cc/test/fake_display_list_recording_source.h
@@ -21,9 +21,7 @@ // display list. class FakeDisplayListRecordingSource : public DisplayListRecordingSource { public: - FakeDisplayListRecordingSource() - : force_unsuitable_for_gpu_rasterization_(false), - playback_allowed_event_(nullptr) {} + FakeDisplayListRecordingSource(); ~FakeDisplayListRecordingSource() override {} static scoped_ptr<FakeDisplayListRecordingSource> CreateRecordingSource( @@ -54,7 +52,10 @@ recorded_viewport_ = recorded_viewport; } - void SetLayerBounds(const gfx::Size& layer_bounds) { size_ = layer_bounds; } + void SetLayerBounds(const gfx::Size& layer_bounds) { + size_ = layer_bounds; + client_.set_bounds(layer_bounds); + } void SetClearCanvasWithDebugColor(bool clear) { clear_canvas_with_debug_color_ = clear; @@ -103,7 +104,10 @@ client_.set_reported_memory_usage(reported_memory_usage); } - void reset_draws() { client_ = FakeContentLayerClient(); } + void reset_draws() { + client_ = FakeContentLayerClient(); + client_.set_bounds(size_); + } void SetUnsuitableForGpuRasterization() { force_unsuitable_for_gpu_rasterization_ = true; @@ -114,9 +118,6 @@ } DisplayItemList* display_list() const { return display_list_.get(); } - void set_pixel_record_distance(int distance) { - pixel_record_distance_ = distance; - } private: FakeContentLayerClient client_;
diff --git a/cc/test/solid_color_content_layer_client.cc b/cc/test/solid_color_content_layer_client.cc index 495e069..97642dd6 100644 --- a/cc/test/solid_color_content_layer_client.cc +++ b/cc/test/solid_color_content_layer_client.cc
@@ -15,6 +15,10 @@ namespace cc { +gfx::Rect SolidColorContentLayerClient::PaintableRegion() { + return gfx::Rect(size_); +} + scoped_refptr<DisplayItemList> SolidColorContentLayerClient::PaintContentsToDisplayList( const gfx::Rect& clip,
diff --git a/cc/test/solid_color_content_layer_client.h b/cc/test/solid_color_content_layer_client.h index c39d567c..a615eb44 100644 --- a/cc/test/solid_color_content_layer_client.h +++ b/cc/test/solid_color_content_layer_client.h
@@ -13,7 +13,10 @@ class SolidColorContentLayerClient : public ContentLayerClient { public: - explicit SolidColorContentLayerClient(SkColor color) : color_(color) {} + explicit SolidColorContentLayerClient(SkColor color, gfx::Size size) + : color_(color), size_(size) {} + + gfx::Rect PaintableRegion() override; // ContentLayerClient implementation. scoped_refptr<DisplayItemList> PaintContentsToDisplayList( @@ -24,6 +27,7 @@ private: SkColor color_; + gfx::Size size_; }; } // namespace cc
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 9d672ac..c9c7495 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -127,7 +127,7 @@ true, false, true, - true, + false, render_surface_layer_list, 0, GetPropertyTrees(root_layer)) {
diff --git a/cc/trees/layer_tree_host_common_perftest.cc b/cc/trees/layer_tree_host_common_perftest.cc index 1373af8..df1a3a2 100644 --- a/cc/trees/layer_tree_host_common_perftest.cc +++ b/cc/trees/layer_tree_host_common_perftest.cc
@@ -55,6 +55,7 @@ ParseTreeFromJson(json_, &content_layer_client_); ASSERT_TRUE(root.get()); layer_tree_host()->SetRootLayer(root); + content_layer_client_.set_bounds(viewport); } void SetTestName(const std::string& name) { test_name_ = name; }
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index bc3ffd5..bb95068 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -61,6 +61,7 @@ public: MockContentLayerClient() {} ~MockContentLayerClient() override {} + gfx::Rect PaintableRegion() override { return gfx::Rect(); } scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { @@ -8360,8 +8361,9 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) { gfx::Transform identity; - FakeContentLayerClient client; scoped_refptr<Layer> root = Layer::Create(layer_settings()); + FakeContentLayerClient client; + client.set_bounds(root->bounds()); scoped_refptr<LayerWithForcedDrawsContent> child = make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); scoped_refptr<LayerWithForcedDrawsContent> grandchild = @@ -8534,8 +8536,9 @@ TEST_F(LayerTreeHostCommonTest, SkippingLayer) { gfx::Transform identity; - FakeContentLayerClient client; scoped_refptr<Layer> root = Layer::Create(layer_settings()); + FakeContentLayerClient client; + client.set_bounds(root->bounds()); scoped_refptr<LayerWithForcedDrawsContent> child = make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings())); SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(),
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc index 6d3313c7..58b604b 100644 --- a/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -32,6 +32,8 @@ bool FillsBoundsCompletely() const override { return false; } size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } + gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { @@ -311,6 +313,7 @@ ~CheckerContentLayerClient() override {} bool FillsBoundsCompletely() const override { return false; } size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } + gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); } scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { @@ -358,6 +361,7 @@ ~CircleContentLayerClient() override {} bool FillsBoundsCompletely() const override { return false; } size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } + gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); } scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override {
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc index 34eba0e0..6f21439 100644 --- a/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -459,9 +459,9 @@ protected: LayerTreeHostReadbackDeviceScalePixelTest() : device_scale_factor_(1.f), - white_client_(SK_ColorWHITE), - green_client_(SK_ColorGREEN), - blue_client_(SK_ColorBLUE) {} + white_client_(SK_ColorWHITE, gfx::Size(200, 200)), + green_client_(SK_ColorGREEN, gfx::Size(200, 200)), + blue_client_(SK_ColorBLUE, gfx::Size(200, 200)) {} void InitializeSettings(LayerTreeSettings* settings) override { // Cause the device scale factor to be inherited by contents scales.
diff --git a/cc/trees/layer_tree_host_pixeltest_synchronous.cc b/cc/trees/layer_tree_host_pixeltest_synchronous.cc index 1eb32ba6..dbddedf 100644 --- a/cc/trees/layer_tree_host_pixeltest_synchronous.cc +++ b/cc/trees/layer_tree_host_pixeltest_synchronous.cc
@@ -34,6 +34,7 @@ gfx::Size bounds(200, 200); FakeContentLayerClient client; + client.set_bounds(bounds); SkPaint green_paint; green_paint.setColor(SkColorSetARGB(255, 0, 255, 0)); client.add_draw_rect(gfx::Rect(bounds), green_paint); @@ -65,12 +66,14 @@ gfx::Size bounds(200, 200); FakeContentLayerClient client; + client.set_bounds(bounds); SkPaint green_paint; green_paint.setColor(SkColorSetARGB(255, 0, 255, 0)); client.add_draw_rect(gfx::Rect(bounds), green_paint); scoped_refptr<PictureLayer> root = PictureLayer::Create(layer_settings(), &client); root->SetBounds(bounds); + client.set_bounds(bounds); root->SetIsDrawable(true); RunSingleThreadedPixelTest(PIXEL_TEST_GL, root,
diff --git a/cc/trees/layer_tree_host_pixeltest_tiles.cc b/cc/trees/layer_tree_host_pixeltest_tiles.cc index 9329721..f9b28aa 100644 --- a/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -105,6 +105,7 @@ explicit BlueYellowClient(const gfx::Size& size) : size_(size), blue_top_(true) {} + gfx::Rect PaintableRegion() override { return gfx::Rect(size_); } scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting painting_status) override {
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 7d2dbef..122a7dc 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -263,6 +263,7 @@ layer_tree_host()->SetRootLayer(root_layer); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer->bounds()); } void AfterTest() override { @@ -333,6 +334,7 @@ layer_tree_host()->SetRootLayer(root_layer); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer->bounds()); } void AfterTest() override { @@ -366,6 +368,7 @@ scoped_refptr<FakePictureLayer> root_layer = FakePictureLayer::Create(layer_settings(), &client_); root_layer->SetBounds(gfx::Size(1024, 1024)); + client_.set_bounds(root_layer->bounds()); root_layer->SetIsDrawable(true); layer_tree_host()->SetRootLayer(root_layer); @@ -731,6 +734,7 @@ layer_tree_host()->SetRootLayer(root_layer_); layer_tree_host()->SetViewportSize(bounds_); PostSetNeedsCommitToMainThread(); + client_.set_bounds(root_layer_->bounds()); } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, @@ -795,6 +799,7 @@ layer_tree_host()->SetViewportSize(bounds_); PostSetNeedsCommitToMainThread(); + client_.set_bounds(root_layer_->bounds()); } void InitializeSettings(LayerTreeSettings* settings) override { @@ -869,6 +874,7 @@ layer_tree_host()->SetRootLayer(root_layer_); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer_->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -924,6 +930,7 @@ layer_tree_host()->SetRootLayer(root_layer_); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer_->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -976,6 +983,7 @@ layer_tree_host()->SetRootLayer(root_layer_); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer_->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -1035,6 +1043,7 @@ layer_tree_host()->SetRootLayer(root_layer_); layer_tree_host()->SetViewportSize(bounds_); PostSetNeedsCommitToMainThread(); + client_.set_bounds(root_layer_->bounds()); } void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { @@ -1136,6 +1145,7 @@ child_layer_ = FakePictureLayer::Create(layer_settings(), &client_); child_layer_->SetBounds(gfx::Size(25, 25)); parent_layer_->AddChild(child_layer_); + client_.set_bounds(root_layer_->bounds()); LayerTreeHostTest::SetupTree(); } @@ -1230,6 +1240,7 @@ layer_tree_host()->SetRootLayer(root_layer_); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer_->bounds()); } void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { @@ -1469,6 +1480,7 @@ layer_settings()); layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f); + client_.set_bounds(root_layer->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -1555,6 +1567,9 @@ void SetTestLayer(Layer* test_layer) { test_layer_ = test_layer; } + gfx::Rect PaintableRegion() override { + return gfx::Rect(test_layer_->bounds()); + } scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { @@ -1628,10 +1643,12 @@ child_layer_->SetIsDrawable(true); child_layer_->SetPosition(gfx::PointF(2.f, 2.f)); child_layer_->SetBounds(gfx::Size(10, 10)); + client_.set_bounds(gfx::Size(10, 10)); layer_tree_host()->SetRootLayer(root_layer_); PostSetNeedsCommitToMainThread(); + client_.set_bounds(root_layer_->bounds()); } void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { @@ -1725,6 +1742,7 @@ layer_tree_host()->root_layer()->AddChild(layer_); PostSetNeedsCommitToMainThread(); + client_.set_bounds(layer_->bounds()); } void DidCommitAndDrawFrame() override { @@ -1906,6 +1924,7 @@ EXPECT_TRUE(layer_tree_host()->settings().can_use_lcd_text); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -2131,6 +2150,7 @@ layer->SetTransform(gfx::Transform(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); layer->SetBounds(gfx::Size(10, 10)); layer_tree_host()->root_layer()->AddChild(layer); + client_.set_bounds(layer->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -2156,6 +2176,8 @@ void set_layer(Layer* layer) { layer_ = layer; } + gfx::Rect PaintableRegion() override { return gfx::Rect(layer_->bounds()); } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, PaintingControlSetting picture_control) override { @@ -2421,6 +2443,7 @@ layer_tree_host()->SetRootLayer(root_layer_); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer_->bounds()); } scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { @@ -2692,6 +2715,7 @@ // Don't set the root layer here. LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void DidCommitAndDrawFrame() override { @@ -3195,6 +3219,7 @@ // Don't set the root layer here. LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void AfterTest() override {} @@ -3798,6 +3823,7 @@ layer_tree_host()->SetRootLayer(root_layer_); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer_->bounds()); } void BeginTest() override { @@ -3859,6 +3885,7 @@ root_->SetBounds(gfx::Size(20, 20)); layer_tree_host()->SetRootLayer(root_); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -4376,6 +4403,7 @@ void SetupTree() override { LayerTreeHostTest::SetupTree(); ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); + client_.set_bounds(layer_tree_host()->root_layer()->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -4432,6 +4460,7 @@ layer->SetBounds(gfx::Size(10, 10)); layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(layer); + layer_client_.set_bounds(layer_->bounds()); } void BeginTest() override { @@ -4487,6 +4516,7 @@ layer->SetBounds(gfx::Size()); layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(layer); + layer_client_.set_bounds(layer->bounds()); } void BeginTest() override { @@ -4544,6 +4574,7 @@ layer->SetBounds(gfx::Size(10, 10)); layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(layer); + layer_client_.set_bounds(layer_->bounds()); } void BeginTest() override { @@ -4614,6 +4645,7 @@ layer->SetBounds(gfx::Size(10, 10)); layer->SetIsDrawable(true); layer_tree_host()->root_layer()->AddChild(layer); + layer_client_.set_bounds(layer_->bounds()); } void BeginTest() override { @@ -4898,9 +4930,6 @@ private: int activation_count_; bool visible_; - - FakeContentLayerClient client_; - scoped_refptr<FakePictureLayer> picture_layer_; }; // TODO(vmpstr): Enable with single thread impl-side painting. @@ -5064,6 +5093,7 @@ layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f); layer_tree_host()->SetRootLayer(root); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root->bounds()); } // Returns the delta scale of all quads in the frame's root pass from their @@ -5250,6 +5280,7 @@ scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(500, 500)); + client_.set_bounds(root->bounds()); scoped_ptr<FakeDisplayListRecordingSource> recording( new FakeDisplayListRecordingSource); @@ -5262,6 +5293,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -5298,11 +5330,13 @@ FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_, std::move(recording)); root->SetBounds(gfx::Size(10000, 10000)); + client_.set_bounds(root->bounds()); root->SetContentsOpaque(true); layer_tree_host()->SetRootLayer(root); LayerTreeHostTest::SetupTree(); layer_tree_host()->SetViewportSize(viewport_size_); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -5360,6 +5394,7 @@ layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f); layer_tree_host()->SetRootLayer(root); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root->bounds()); } // Returns the delta scale of all quads in the frame's root pass from their @@ -5513,6 +5548,7 @@ layer_tree_host()->SetRootLayer(root_layer); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer->bounds()); } void BeginTest() override { @@ -5579,6 +5615,7 @@ root_layer->AddChild(child_layer); layer_tree_host()->SetRootLayer(root_layer); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -5655,6 +5692,7 @@ layer_tree_host()->SetRootLayer(root_layer); LayerTreeHostTest::SetupTree(); + client_.set_bounds(root_layer->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -5809,6 +5847,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -5893,6 +5932,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -5981,6 +6021,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -6072,6 +6113,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -6170,6 +6212,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); }
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index e7cfa62d..d09234d 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -233,6 +233,7 @@ LayerTreeHostAnimationTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(picture_->bounds()); layer_tree_host()->root_layer()->AddChild(picture_); } @@ -284,6 +285,7 @@ LayerTreeHostAnimationTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(picture_->bounds()); picture_->set_layer_animation_delegate(this); layer_tree_host()->root_layer()->AddChild(picture_); } @@ -366,6 +368,7 @@ void SetupTree() override { update_check_layer_->SetOpacity(0.f); layer_tree_host()->SetRootLayer(update_check_layer_); + client_.set_bounds(update_check_layer_->bounds()); LayerTreeHostAnimationTest::SetupTree(); } @@ -555,6 +558,7 @@ LayerTreeHostAnimationTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(picture_->bounds()); picture_->set_layer_animation_delegate(this); layer_tree_host()->root_layer()->AddChild(picture_); } @@ -637,6 +641,7 @@ scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); scroll_layer_->SetBounds(gfx::Size(1000, 1000)); + client_.set_bounds(scroll_layer_->bounds()); scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); } @@ -695,6 +700,7 @@ scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); + client_.set_bounds(scroll_layer_->bounds()); scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); @@ -882,6 +888,7 @@ layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(2, 2)); + client_.set_bounds(layer_->bounds()); // Transform the layer to 4,4 to start. gfx::Transform start_transform; start_transform.Translate(4.0, 4.0); @@ -1054,6 +1061,7 @@ LayerTreeHostAnimationTest::SetupTree(); layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(layer_->bounds()); layer_tree_host()->root_layer()->AddChild(layer_); } @@ -1129,6 +1137,7 @@ LayerTreeHostAnimationTest::SetupTree(); layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(layer_->bounds()); layer_tree_host()->root_layer()->AddChild(layer_); } @@ -1209,6 +1218,7 @@ LayerTreeHostAnimationTest::SetupTree(); layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(layer_->bounds()); layer_tree_host()->root_layer()->AddChild(layer_); } @@ -1279,6 +1289,7 @@ LayerTreeHostAnimationTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(picture_->bounds()); picture_->set_layer_animation_delegate(this); layer_tree_host()->root_layer()->AddChild(picture_); }
diff --git a/cc/trees/layer_tree_host_unittest_animation_timelines.cc b/cc/trees/layer_tree_host_unittest_animation_timelines.cc index c95a5ca1..f1b3e2f 100644 --- a/cc/trees/layer_tree_host_unittest_animation_timelines.cc +++ b/cc/trees/layer_tree_host_unittest_animation_timelines.cc
@@ -204,6 +204,7 @@ LayerTreeHostTimelinesTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(picture_->bounds()); layer_tree_host()->root_layer()->AddChild(picture_); AttachPlayersToTimeline(); @@ -266,6 +267,7 @@ LayerTreeHostTimelinesTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(picture_->bounds()); layer_tree_host()->root_layer()->AddChild(picture_); @@ -363,6 +365,7 @@ void SetupTree() override { update_check_layer_->SetOpacity(0.f); layer_tree_host()->SetRootLayer(update_check_layer_); + client_.set_bounds(update_check_layer_->bounds()); LayerTreeHostTimelinesTest::SetupTree(); AttachPlayersToTimeline(); @@ -453,6 +456,7 @@ LayerTreeHostTimelinesTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(picture_->bounds()); layer_tree_host()->root_layer()->AddChild(picture_); AttachPlayersToTimeline(); @@ -543,6 +547,7 @@ scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); scroll_layer_->SetBounds(gfx::Size(1000, 1000)); + client_.set_bounds(scroll_layer_->bounds()); scroll_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); @@ -604,6 +609,7 @@ scroll_layer_ = FakePictureLayer::Create(layer_settings(), &client_); scroll_layer_->SetScrollClipLayerId(layer_tree_host()->root_layer()->id()); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); + client_.set_bounds(scroll_layer_->bounds()); scroll_layer_->SetScrollOffset(gfx::ScrollOffset(100.0, 200.0)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); @@ -877,6 +883,7 @@ LayerTreeHostTimelinesTest::SetupTree(); layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(layer_->bounds()); layer_tree_host()->root_layer()->AddChild(layer_); AttachPlayersToTimeline(); @@ -935,6 +942,7 @@ LayerTreeHostTimelinesTest::SetupTree(); layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(layer_->bounds()); layer_tree_host()->root_layer()->AddChild(layer_); AttachPlayersToTimeline(); @@ -1004,6 +1012,9 @@ : public LayerTreeHostTimelinesTest { public: void SetupTree() override { + prev_screen_space_transform_is_animating_ = true; + screen_space_transform_animation_stopped_ = false; + LayerTreeHostTimelinesTest::SetupTree(); AttachPlayersToTimeline(); player_->AttachLayer(layer_tree_host()->root_layer()->id()); @@ -1013,24 +1024,11 @@ void BeginTest() override { PostSetNeedsCommitToMainThread(); } void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { - if (host_impl->active_tree()->source_frame_number() == 1) { - EXPECT_TRUE(host_impl->active_tree()); - EXPECT_TRUE(host_impl->active_tree()->root_layer()); - EXPECT_TRUE(host_impl->pending_tree()); - EXPECT_TRUE(host_impl->pending_tree()->root_layer()); - - EXPECT_EQ(2, host_impl->pending_tree()->source_frame_number()); - - EXPECT_TRUE(host_impl->active_tree() + if (host_impl->pending_tree()->source_frame_number() <= 1) { + EXPECT_TRUE(host_impl->pending_tree() ->root_layer() ->screen_space_transform_is_animating()); - EXPECT_FALSE(host_impl->pending_tree() - ->root_layer() - ->screen_space_transform_is_animating()); - } else if (host_impl->active_tree()->source_frame_number() == 2) { - EXPECT_FALSE(host_impl->active_tree() - ->root_layer() - ->screen_space_transform_is_animating()); + } else { EXPECT_FALSE(host_impl->pending_tree() ->root_layer() ->screen_space_transform_is_animating()); @@ -1047,12 +1045,44 @@ } } + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame_data, + DrawResult draw_result) override { + const bool screen_space_transform_is_animating = + host_impl->active_tree() + ->root_layer() + ->screen_space_transform_is_animating(); + + // Check that screen_space_transform_is_animating changes only once. + if (screen_space_transform_is_animating && + prev_screen_space_transform_is_animating_) + EXPECT_FALSE(screen_space_transform_animation_stopped_); + if (!screen_space_transform_is_animating && + prev_screen_space_transform_is_animating_) { + EXPECT_FALSE(screen_space_transform_animation_stopped_); + screen_space_transform_animation_stopped_ = true; + } + if (!screen_space_transform_is_animating && + !prev_screen_space_transform_is_animating_) + EXPECT_TRUE(screen_space_transform_animation_stopped_); + + prev_screen_space_transform_is_animating_ = + screen_space_transform_is_animating; + + return draw_result; + } + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { if (host_impl->active_tree()->source_frame_number() >= 2) EndTest(); } - void AfterTest() override {} + void AfterTest() override { + EXPECT_TRUE(screen_space_transform_animation_stopped_); + } + + bool prev_screen_space_transform_is_animating_; + bool screen_space_transform_animation_stopped_; }; MULTI_THREAD_TEST_F( @@ -1066,6 +1096,7 @@ LayerTreeHostTimelinesTest::SetupTree(); layer_ = FakePictureLayer::Create(layer_settings(), &client_); layer_->SetBounds(gfx::Size(4, 4)); + client_.set_bounds(layer_->bounds()); layer_tree_host()->root_layer()->AddChild(layer_); AttachPlayersToTimeline();
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index 174af321..ead16f2 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -636,6 +636,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostContextTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void InvalidateAndSetNeedsCommit() override { @@ -709,6 +710,7 @@ scoped_refptr<FakePictureLayer> picture_layer = FakePictureLayer::Create(layer_settings(), &client_); picture_layer->SetBounds(gfx::Size(10, 20)); + client_.set_bounds(picture_layer->bounds()); layer_tree_host()->SetRootLayer(picture_layer); LayerTreeHostContextTest::SetupTree(); @@ -843,6 +845,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostContextTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -983,6 +986,7 @@ scoped_refptr<PictureLayer> mask = PictureLayer::Create(layer_settings_, &client_); mask->SetBounds(gfx::Size(10, 10)); + client_.set_bounds(mask->bounds()); scoped_refptr<PictureLayer> layer_with_mask = PictureLayer::Create(layer_settings_, &client_); @@ -1135,6 +1139,7 @@ scoped_refptr<PictureLayer> picture = PictureLayer::Create(layer_settings(), &client_); picture->SetBounds(gfx::Size(10, 10)); + client_.set_bounds(picture->bounds()); picture->SetIsDrawable(true); root->AddChild(picture);
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc index f6bd32a..9e39762 100644 --- a/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -36,6 +36,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -191,6 +192,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { @@ -289,6 +291,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void AddCopyRequest(Layer* layer) { @@ -389,6 +392,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { @@ -462,6 +466,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { @@ -504,6 +509,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void AddCopyRequest(Layer* layer) { @@ -599,6 +605,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -723,6 +730,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { @@ -877,6 +885,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { @@ -954,6 +963,7 @@ layer_tree_host()->SetRootLayer(root_); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root_->bounds()); } void BeginTest() override { @@ -1027,6 +1037,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeHostCopyRequestTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override {
diff --git a/cc/trees/layer_tree_host_unittest_damage.cc b/cc/trees/layer_tree_host_unittest_damage.cc index 6ca11e9..a1c4cdf 100644 --- a/cc/trees/layer_tree_host_unittest_damage.cc +++ b/cc/trees/layer_tree_host_unittest_damage.cc
@@ -33,6 +33,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeHostDamageTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { @@ -95,6 +96,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeHostDamageTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { @@ -167,6 +169,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeHostDamageTest::SetupTree(); + client_.set_bounds(root->bounds()); } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, @@ -251,6 +254,7 @@ root_->AddChild(child_); layer_tree_host()->SetRootLayer(root_); LayerTreeHostDamageTest::SetupTree(); + client_.set_bounds(root_->bounds()); } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, @@ -363,6 +367,7 @@ EXPECT_FALSE(content_rect.Intersects(scrollbar_rect)); LayerTreeHostDamageTest::SetupTree(); + client_.set_bounds(root_layer->bounds()); } private:
diff --git a/cc/trees/layer_tree_host_unittest_occlusion.cc b/cc/trees/layer_tree_host_unittest_occlusion.cc index 13496f5..75858d1 100644 --- a/cc/trees/layer_tree_host_unittest_occlusion.cc +++ b/cc/trees/layer_tree_host_unittest_occlusion.cc
@@ -159,6 +159,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -231,6 +232,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); }
diff --git a/cc/trees/layer_tree_host_unittest_picture.cc b/cc/trees/layer_tree_host_unittest_picture.cc index ec42144..8dec5860 100644 --- a/cc/trees/layer_tree_host_unittest_picture.cc +++ b/cc/trees/layer_tree_host_unittest_picture.cc
@@ -25,6 +25,7 @@ root->AddChild(root_picture_layer_); layer_tree_host()->SetRootLayer(root); + client_.set_bounds(size); } scoped_refptr<FakePictureLayer> root_picture_layer_; @@ -142,7 +143,7 @@ void SetupTree() override { scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(768, 960)); - + client_.set_bounds(root->bounds()); client_.set_fill_with_nonsolid_color(true); picture_ = FakePictureLayer::Create(layer_settings(), &client_); picture_->SetBounds(gfx::Size(768, 960)); @@ -205,7 +206,6 @@ scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); - // The layer is big enough that the live tiles rect won't cover the full // layer. client_.set_fill_with_nonsolid_color(true); @@ -219,6 +219,7 @@ layer_tree_host()->SetRootLayer(root); LayerTreeHostPictureTest::SetupTree(); + client_.set_bounds(picture_->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -311,6 +312,7 @@ void SetupTree() override { scoped_refptr<Layer> root = Layer::Create(layer_settings()); root->SetBounds(gfx::Size(100, 100)); + client_.set_bounds(root->bounds()); child_ = Layer::Create(layer_settings()); root->AddChild(child_); @@ -417,6 +419,7 @@ layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f); layer_tree_host()->SetRootLayer(root); LayerTreeHostPictureTest::SetupTree(); + client_.set_bounds(picture_->bounds()); } void InitializeSettings(LayerTreeSettings* settings) override {
diff --git a/cc/trees/layer_tree_host_unittest_proxy.cc b/cc/trees/layer_tree_host_unittest_proxy.cc index 78545ef..2605dd9 100644 --- a/cc/trees/layer_tree_host_unittest_proxy.cc +++ b/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -81,6 +81,7 @@ void SetupTree() override { layer_tree_host()->SetRootLayer(update_check_layer_); ProxyTest::SetupTree(); + client_.set_bounds(update_check_layer_->bounds()); } const ThreadProxy::MainThreadOnly& ThreadProxyMainOnly() const {
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index 9ee2ba27..411092ce 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -510,6 +510,7 @@ layer_tree_host()->SetRootLayer(root_layer); LayerTreeTest::SetupTree(); + fake_content_layer_client_.set_bounds(root_layer->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -1150,6 +1151,7 @@ CreateScrollLayer(outer_scroll_layer, &root_scroll_layer_client_); CreateScrollLayer(outer_scroll_layer, &sibling_scroll_layer_client_); CreateScrollLayer(root_scroll_layer, &child_scroll_layer_client_); + fake_content_layer_client_.set_bounds(root_layer->bounds()); } void BeginTest() override { PostSetNeedsCommitToMainThread(); }
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index c20f6f5..077f1b3 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc
@@ -60,7 +60,7 @@ use_occlusion_for_tile_prioritization(false), record_full_layer(false), verify_property_trees(false), - use_property_trees(true), + use_property_trees(false), image_decode_tasks_enabled(false), use_compositor_animation_timelines(false), wait_for_beginframe_interval(true),
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 305d2df..161cf0d 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -141,8 +141,6 @@ ":file_pre_reader", # 'chrome_nacl_win64" TODO(GYP) bug 512869 - # '../win8/delegate_execute/delegate_execute.gyp:*', TODO(GYP) bug 512867 - # '../win8/metro_driver/metro_driver.gyp:metro_driver', TODO(GYP) bug 512864 "//base", "//breakpad:breakpad_handler", "//breakpad:breakpad_sender", @@ -155,11 +153,14 @@ "//components/browser_watcher:browser_watcher_client", "//components/crash/content/app", "//components/crash/core/common", + "//components/flags_ui:switches", "//content:sandbox_helper_win", "//content/public/common:static_switches", "//crypto", "//sandbox", "//ui/gfx", + "//win8/delegate_execute", + "//win8/metro_driver", ] data_deps = [ "//chrome/app/version_assembly:version_assembly_manifest",
diff --git a/chrome/VERSION b/chrome/VERSION index 00b5e795..309eed7 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=49 MINOR=0 -BUILD=2573 +BUILD=2574 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 9863806..f7b81e3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1191,6 +1191,13 @@ } /** + * @return The {@code ReaderModeManager} or {@code null} if none; + */ + public ReaderModeManager getReaderModeManager() { + return mReaderModeManager; + } + + /** * Create a full-screen manager to be used by this activity. * @param controlContainer The control container that will be controlled by the full-screen * manager.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java index 09aa342..5ba99496 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java
@@ -24,7 +24,7 @@ /** * The operation succeeded. Note that this value will only be returned for dry runs, because - * sucessfully resetting data will kill this process and return + * successfully resetting data will kill this process and return * {@link Activity#RESULT_CANCELED}. */ private static final int RESULT_OK = Activity.RESULT_OK;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java index 3c80f13a..4fccfb72 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java
@@ -1410,7 +1410,12 @@ public void showPromoViewAtYPosition(float y) { if (mPromoView == null || !isPromoVisible()) return; - mPromoView.setTranslationX(getOffsetX() / mPxToDp); + float offsetX = getOffsetX() / mPxToDp; + if (LocalizationUtils.isLayoutRtl()) { + offsetX = -offsetX; + } + + mPromoView.setTranslationX(offsetX); mPromoView.setTranslationY(y); mPromoView.setVisibility(View.VISIBLE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java index ba8bf36a..ea3bf11f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.compositor.layouts; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; import android.text.TextUtils; @@ -149,7 +150,7 @@ mTabObserver = new TabModelSelectorTabObserver(selector) { @Override - public void onFaviconUpdated(Tab tab) { + public void onFaviconUpdated(Tab tab, Bitmap icon) { updateTitle(tab); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index 1ba524a..de57765 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -33,12 +33,16 @@ // Translation. @VisibleForTesting static final String DISABLE_FORCE_TRANSLATION_ONEBOX = "disable_force_translation_onebox"; + @VisibleForTesting + static final String DISABLE_AUTO_DETECT_TRANSLATION_ONEBOX = + "disable_auto_detect_translation_onebox"; // Cached values to avoid repeated and redundant JNI operations. private static Boolean sEnabled; private static Boolean sIsPeekPromoEnabled; private static Integer sPeekPromoMaxCount; private static Boolean sDisableForceTranslationOnebox; + private static Boolean sDisableAutoDetectTranslationOnebox; /** * Don't instantiate. @@ -139,6 +143,18 @@ return sDisableForceTranslationOnebox.booleanValue(); } + /** + * @return Whether forcing a translation Onebox based on auto-detection of the source language + * is disabled. + */ + static boolean disableAutoDetectTranslationOnebox() { + if (sDisableAutoDetectTranslationOnebox == null) { + sDisableAutoDetectTranslationOnebox = getBooleanParam( + DISABLE_AUTO_DETECT_TRANSLATION_ONEBOX); + } + return sDisableAutoDetectTranslationOnebox.booleanValue(); + } + // -------------------------------------------------------------------------------------------- // Helpers. // --------------------------------------------------------------------------------------------
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index a8f3a97..1aa77c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -492,7 +492,7 @@ boolean shouldPrefetch = mPolicy.shouldPrefetchSearchResult(isTap); mSearchRequest = new ContextualSearchRequest(mSelectionController.getSelectedText(), null, shouldPrefetch); - // TODO(donnd): figure out a way to do translation on long-press selections. + forceAutoDetectTranslateUnlessDisabled(mSearchRequest); mDidStartLoadingResolvedSearchRequest = false; mSearchPanel.displaySearchTerm(mSelectionController.getSelectedText()); if (shouldPrefetch) loadSearchUrl(); @@ -738,16 +738,7 @@ boolean shouldPreload = !doPreventPreload && mPolicy.shouldPrefetchSearchResult(true); mSearchRequest = new ContextualSearchRequest(searchTerm, alternateTerm, shouldPreload); // Trigger translation, if enabled. - if (!contextLanguage.isEmpty()) { - if (mPolicy.needsTranslation(contextLanguage, getReadableLanguages())) { - boolean doForceTranslate = !mPolicy.disableForceTranslationOnebox(); - if (doForceTranslate) { - mSearchRequest.forceTranslation(contextLanguage, - mPolicy.bestTargetLanguage(getWritableLanguages())); - } - ContextualSearchUma.logTranslateOnebox(doForceTranslate); - } - } + forceTranslateIfNeeded(mSearchRequest, contextLanguage); mDidStartLoadingResolvedSearchRequest = false; if (mSearchPanel.isContentShowing()) { mSearchRequest.setNormalPriority(); @@ -797,6 +788,7 @@ // ============================================================================================ // Translation support + // TODO(donnd): move to a separate file. // ============================================================================================ /** @@ -871,6 +863,48 @@ return new Locale(trimmedLocale).getLanguage(); } + /** + * Force translation from the given language for the current search request, + * unless disabled by experiment. Also log whenever conditions are right to translate. + * @param searchRequest The search request to force translation upon. + * @param sourceLanguage The language to translate from, or an empty string if not known. + */ + private void forceTranslateIfNeeded(ContextualSearchRequest searchRequest, + String sourceLanguage) { + if (!TextUtils.isEmpty(sourceLanguage)) { + if (mPolicy.needsTranslation(sourceLanguage, getReadableLanguages())) { + boolean doForceTranslate = !mPolicy.disableForceTranslationOnebox(); + if (doForceTranslate && searchRequest != null) { + searchRequest.forceTranslation(sourceLanguage, + mPolicy.bestTargetLanguage(getWritableLanguages())); + } + // Log that conditions were right for translation, even though it may be disabled + // for an experiment so we can compare with the counter factual data. + ContextualSearchUma.logTranslateOnebox(doForceTranslate); + } + } + } + + /** + * Force auto-detect translation for the current search request unless disabled by experiment. + * Also log that conditions are right to translate. + * @param searchRequest The search request to force translation upon. + */ + private void forceAutoDetectTranslateUnlessDisabled(ContextualSearchRequest searchRequest) { + // Always trigger translation using auto-detect when we're not resolving, + // unless disabled by policy. + boolean shouldAutoDetectTranslate = !mPolicy.disableAutoDetectTranslationOnebox(); + if (shouldAutoDetectTranslate && searchRequest != null) { + // The translation one-box won't actually show when the source text ends up being + // the same as the target text, so we err on over-triggering. + searchRequest.forceAutoDetectTranslation( + mPolicy.bestTargetLanguage(getWritableLanguages())); + } + // Log that conditions were right for translation, even though it may be disabled + // for an experiment so we can compare with the counter factual data. + ContextualSearchUma.logTranslateOnebox(shouldAutoDetectTranslate); + } + // ============================================================================================ // OverlayContentDelegate // ============================================================================================
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java index 089109d..3041cb31 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -472,6 +472,16 @@ } /** + * @return Whether forcing a translation Onebox based on auto-detection of the source language + * is disabled. + */ + boolean disableAutoDetectTranslationOnebox() { + if (disableForceTranslationOnebox()) return true; + + return ContextualSearchFieldTrial.disableAutoDetectTranslationOnebox(); + } + + /** * Sets the limit for the tap triggered promo. */ @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java index 4264d9e..277d1219 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java
@@ -161,6 +161,15 @@ } /** + * Adds translation parameters that will trigger auto-detection of the source language. + * @param targetLanguage The language the that the user prefers. + */ + void forceAutoDetectTranslation(String targetLanguage) { + // Use the empty string for the source language in order to trigger auto-detect. + forceTranslation("", targetLanguage); + } + + /** * @return Whether translation was forced for this request. */ @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java index 87cb047..44b0ab5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/datausage/ExternalDataUseObserver.java
@@ -98,7 +98,7 @@ /* * {@link #onReportDataUseDone} reports the result of {@link #reportDataUse} to * the native. - * @param success true if the data report was sucessfully submitted to the external observer. + * @param success true if the data report was successfully submitted to the external observer. */ protected void onReportDataUseDone(boolean success) { // Check if native object is destroyed. This may happen at the time of Chromium shutdown.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java index 4fea461..14e8814 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java
@@ -29,7 +29,6 @@ import org.chromium.chrome.browser.TabState; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; import org.chromium.chrome.browser.compositor.layouts.LayoutManagerDocument; -import org.chromium.chrome.browser.document.DocumentTab.DocumentTabObserver; import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkUtils; import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; import org.chromium.chrome.browser.firstrun.FirstRunStatus; @@ -42,10 +41,12 @@ import org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoScreen; import org.chromium.chrome.browser.signin.SigninPromoScreen; import org.chromium.chrome.browser.ssl.ConnectionSecurityLevel; +import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabUma.TabCreationState; import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; +import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; import org.chromium.chrome.browser.tabmodel.document.ActivityDelegate; import org.chromium.chrome.browser.tabmodel.document.AsyncTabCreationParams; import org.chromium.chrome.browser.tabmodel.document.AsyncTabCreationParamsManager; @@ -87,6 +88,109 @@ // plus add another 20ms for a re-layout. private static final int MENU_EXIT_ANIMATION_WAIT_MS = 170; + private class DocumentTabObserver extends EmptyTabObserver { + @Override + public void onPageLoadStarted(Tab tab, String url) { + // Discard startup navigation measurements when the user interfered and started the + // 2nd navigation (in activity lifetime) in parallel. + if (!sIsFirstPageLoadStart) { + UmaUtils.setRunningApplicationStart(false); + } else { + sIsFirstPageLoadStart = false; + } + } + + @Override + public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) { + if (!didStartLoad) return; + resetIcon(); + } + + @Override + public void onFaviconUpdated(Tab tab, Bitmap icon) { + if (mLargestFavicon == null || icon.getWidth() > mLargestFavicon.getWidth() + || icon.getHeight() > mLargestFavicon.getHeight()) { + mLargestFavicon = icon; + updateTaskDescription(); + } + } + + @Override + public void onUrlUpdated(Tab tab) { + assert mDocumentTab == tab; + + updateTaskDescription(); + mTabModel.updateEntry(getIntent(), mDocumentTab); + } + + @Override + public void onTitleUpdated(Tab tab) { + super.onTitleUpdated(tab); + updateTaskDescription(); + } + + @Override + public void onSSLStateUpdated(Tab tab) { + if (hasSecurityWarningOrError(tab)) resetIcon(); + } + + @Override + public void onDidNavigateMainFrame(Tab tab, String url, String baseUrl, + boolean isNavigationToDifferentPage, boolean isFragmentNavigation, + int statusCode) { + if (!isNavigationToDifferentPage) return; + mLargestFavicon = null; + } + + @Override + public void onLoadStopped(Tab tab, boolean toDifferentDocument) { + assert mDocumentTab == tab; + + updateTaskDescription(); + mTabModel.updateEntry(getIntent(), mDocumentTab); + } + + @Override + public void onDidChangeThemeColor(Tab tab, int color) { + updateTaskDescription(); + } + + @Override + public void onDidAttachInterstitialPage(Tab tab) { + resetIcon(); + } + + @Override + public void onDidDetachInterstitialPage(Tab tab) { + resetIcon(); + } + + @Override + public void onCrash(Tab tab, boolean sadTabShown) { + int currentState = ApplicationStatus.getStateForActivity(DocumentActivity.this); + if (currentState != ActivityState.STOPPED) return; + + if (!isTaskRoot() || IntentUtils.safeGetBooleanExtra(getIntent(), + IntentHandler.EXTRA_APPEND_TASK, false)) { + return; + } + + // Finishing backgrounded Activities whose renderers have crashed allows us to + // destroy them and return resources sooner than if we wait for Android to destroy + // the Activities themselves. Problematically, this also removes + // IncognitoDocumentActivity instances from Android's Recents menu and auto-closes + // the tab. Instead, take a hit and keep the Activities alive -- Android will + // eventually destroy the Activities, anyway (crbug.com/450292). + if (!isIncognito()) finish(); + } + + private boolean hasSecurityWarningOrError(Tab tab) { + int securityLevel = tab.getSecurityLevel(); + return securityLevel == ConnectionSecurityLevel.SECURITY_ERROR + || securityLevel == ConnectionSecurityLevel.SECURITY_WARNING + || securityLevel == ConnectionSecurityLevel.SECURITY_POLICY_WARNING; + } + } private DocumentTabModel mTabModel; private InitializationObserver mTabInitializationObserver; @@ -376,6 +480,7 @@ if (asyncParams != null && asyncParams.getLoadUrlParams().getUrl() != null) { loadLastKnownUrl(asyncParams); } + mDocumentTab.show(TabSelectionType.FROM_USER); } StartupMetrics.getInstance().recordHistogram(false); } @@ -531,110 +636,7 @@ mDocumentTab.setFullscreenManager(getFullscreenManager()); - mDocumentTab.addObserver(new DocumentTabObserver() { - @Override - public void onPageLoadStarted(Tab tab, String url) { - // Discard startup navigation measurements when the user interfered and started the - // 2nd navigation (in activity lifetime) in parallel. - if (!sIsFirstPageLoadStart) { - UmaUtils.setRunningApplicationStart(false); - } else { - sIsFirstPageLoadStart = false; - } - } - - @Override - public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) { - if (!didStartLoad) return; - resetIcon(); - } - - @Override - protected void onFaviconReceived(Bitmap image) { - super.onFaviconReceived(image); - if (mLargestFavicon == null || image.getWidth() > mLargestFavicon.getWidth() - || image.getHeight() > mLargestFavicon.getHeight()) { - mLargestFavicon = image; - updateTaskDescription(); - } - } - - @Override - public void onUrlUpdated(Tab tab) { - assert mDocumentTab == tab; - - updateTaskDescription(); - mTabModel.updateEntry(getIntent(), mDocumentTab); - } - - @Override - public void onTitleUpdated(Tab tab) { - super.onTitleUpdated(tab); - updateTaskDescription(); - } - - @Override - public void onSSLStateUpdated(Tab tab) { - if (hasSecurityWarningOrError(tab)) resetIcon(); - } - - @Override - public void onDidNavigateMainFrame(Tab tab, String url, String baseUrl, - boolean isNavigationToDifferentPage, boolean isFragmentNavigation, - int statusCode) { - if (!isNavigationToDifferentPage) return; - mLargestFavicon = null; - } - - @Override - public void onLoadStopped(Tab tab, boolean toDifferentDocument) { - assert mDocumentTab == tab; - - updateTaskDescription(); - mTabModel.updateEntry(getIntent(), mDocumentTab); - } - - @Override - public void onDidChangeThemeColor(Tab tab, int color) { - updateTaskDescription(); - } - - @Override - public void onDidAttachInterstitialPage(Tab tab) { - resetIcon(); - } - - @Override - public void onDidDetachInterstitialPage(Tab tab) { - resetIcon(); - } - - @Override - public void onCrash(Tab tab, boolean sadTabShown) { - int currentState = ApplicationStatus.getStateForActivity(DocumentActivity.this); - if (currentState != ActivityState.STOPPED) return; - - if (!isTaskRoot() || IntentUtils.safeGetBooleanExtra(getIntent(), - IntentHandler.EXTRA_APPEND_TASK, false)) { - return; - } - - // Finishing backgrounded Activities whose renderers have crashed allows us to - // destroy them and return resources sooner than if we wait for Android to destroy - // the Activities themselves. Problematically, this also removes - // IncognitoDocumentActivity instances from Android's Recents menu and auto-closes - // the tab. Instead, take a hit and keep the Activities alive -- Android will - // eventually destroy the Activities, anyway (crbug.com/450292). - if (!isIncognito()) finish(); - } - - private boolean hasSecurityWarningOrError(Tab tab) { - int securityLevel = tab.getSecurityLevel(); - return securityLevel == ConnectionSecurityLevel.SECURITY_ERROR - || securityLevel == ConnectionSecurityLevel.SECURITY_WARNING - || securityLevel == ConnectionSecurityLevel.SECURITY_POLICY_WARNING; - } - }); + mDocumentTab.addObserver(new DocumentTabObserver()); removeWindowBackground();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java index ac43565..39eedff9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java
@@ -5,9 +5,7 @@ package org.chromium.chrome.browser.document; import android.app.Activity; -import android.graphics.Bitmap; -import org.chromium.base.ObserverList.RewindableIterator; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.IntentHandler; @@ -15,10 +13,8 @@ import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; -import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabDelegateFactory; -import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab.TabUma; import org.chromium.chrome.browser.tab.TabUma.TabCreationState; import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid; @@ -32,17 +28,6 @@ * A Tab child class with Chrome documents specific functionality. */ public class DocumentTab extends Tab { - /** - * Observer class with extra calls specific to Chrome Documents - */ - public static class DocumentTabObserver extends EmptyTabObserver { - /** - * Called when a Favicon is received for the current document. - * @param image The favicon image that was received. - */ - protected void onFaviconReceived(Bitmap image) { } - } - private boolean mDidRestoreState; /** @@ -125,19 +110,6 @@ getView().requestFocus(); } - @Override - public void onFaviconAvailable(Bitmap image) { - super.onFaviconAvailable(image); - if (image == null) return; - RewindableIterator<TabObserver> observers = getTabObservers(); - while (observers.hasNext()) { - TabObserver observer = observers.next(); - if (observer instanceof DocumentTabObserver) { - ((DocumentTabObserver) observer).onFaviconReceived(image); - } - } - } - /** * A web contents delegate for handling opening new windows in Document mode. */ @@ -192,6 +164,13 @@ } } + @Override + public void onActivityStart() { + // DocumentActivity#onResumeWithNative() will call Tab.show(), and so we don't need to call + // it at this point. + onActivityStartInternal(false /* showNow */); + } + /** * A helper function to create TabUma and set it to the tab. * @param creationState In what state the tab was created.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index e00460f..34d789b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -71,7 +71,7 @@ private int mTabId; // The ReaderModePanel that this class is managing. - private ReaderModePanel mReaderModePanel; + protected ReaderModePanel mReaderModePanel; // The ChromeActivity that this panel exists in. private ChromeActivity mChromeActivity; @@ -289,7 +289,7 @@ return tab.getWebContents(); } - private WebContentsObserver createWebContentsObserver(WebContents webContents) { + protected WebContentsObserver createWebContentsObserver(WebContents webContents) { final int readerTabId = mTabModelSelector.getCurrentTabId(); if (readerTabId == Tab.INVALID_TAB_ID) return null; @@ -299,9 +299,14 @@ boolean isMainFrame, String validatedUrl, boolean isErrorPage, boolean isIframeSrcdoc) { if (!isMainFrame) return; - mTabStatusMap.get(readerTabId).setUrl(validatedUrl); + + // Make sure the tab was not destroyed. + ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); + if (tabInfo == null) return; + + tabInfo.setUrl(validatedUrl); if (DomDistillerUrlUtils.isDistilledPage(validatedUrl)) { - mTabStatusMap.get(readerTabId).setStatus(STARTED); + tabInfo.setStatus(STARTED); closeReaderPanel(StateChangeReason.UNKNOWN, true); mReaderModePageUrl = validatedUrl; } @@ -316,16 +321,20 @@ if (isNavigationInPage) return; if (DomDistillerUrlUtils.isDistilledPage(url)) return; - mTabStatusMap.get(readerTabId).setStatus(POSSIBLE); + // Make sure the tab was not destroyed. + ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); + if (tabInfo == null) return; + + tabInfo.setStatus(POSSIBLE); if (!TextUtils.equals(url, DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl( mReaderModePageUrl))) { - mTabStatusMap.get(readerTabId).setStatus(NOT_POSSIBLE); + tabInfo.setStatus(NOT_POSSIBLE); mIsUmaRecorded = false; } mReaderModePageUrl = null; - if (mTabStatusMap.containsKey(readerTabId) - && mTabStatusMap.get(readerTabId).getStatus() != POSSIBLE) { + + if (tabInfo.getStatus() != POSSIBLE) { closeReaderPanel(StateChangeReason.UNKNOWN, false); } else { requestReaderPanelShow(StateChangeReason.UNKNOWN); @@ -339,7 +348,7 @@ * showing. * @param reason The reason the panel is requesting to be shown. */ - private void requestReaderPanelShow(StateChangeReason reason) { + protected void requestReaderPanelShow(StateChangeReason reason) { int currentTabId = mTabModelSelector.getCurrentTabId(); if (currentTabId == Tab.INVALID_TAB_ID) return; @@ -359,7 +368,7 @@ * @param reason The reason the panel is closing. * @param animate True if the panel should animate closed. */ - private void closeReaderPanel(StateChangeReason reason, boolean animate) { + protected void closeReaderPanel(StateChangeReason reason, boolean animate) { if (mReaderModePanel == null) return; mReaderModePanel.closePanel(reason, animate); } @@ -409,10 +418,14 @@ new DistillablePageUtils.PageDistillableDelegate() { @Override public void onIsPageDistillableResult(boolean isDistillable, boolean isLast) { - if (!mTabStatusMap.containsKey(readerTabId)) return; ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); - Tab readerTab = mTabModelSelector.getTabById(readerTabId); + + // It is possible that the tab was destroyed before this callback happens. + // TODO(wychen/mdjones): Remove the callback when a Tab/WebContents is + // destroyed so that this never happens. + if (readerTab == null || tabInfo == null) return; + // Make sure the page didn't navigate while waiting for a response. if (!readerTab.getUrl().equals(tabInfo.getUrl())) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java index b82177b..66d6c0d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -514,7 +514,7 @@ if (downloadInfo.getFilePath() != null) { File file = new File(downloadInfo.getFilePath()); if (!file.delete()) { - Log.w(TAG, "Failed to remove the unsucessful download"); + Log.w(TAG, "Failed to remove the unsuccessful download"); } } return INVALID_DOWNLOAD_ID;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java index db4aa505..567a5b0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java
@@ -4,15 +4,16 @@ package org.chromium.chrome.browser.media.router; +import android.app.Activity; import android.content.Context; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; -import android.support.v7.app.MediaRouteDialogFactory; import android.support.v7.media.MediaRouter; +import android.view.View; +import android.widget.FrameLayout; import org.chromium.base.ApplicationStatus; -import org.chromium.chrome.browser.media.remote.ChromeMediaRouteDialogFactory; import org.chromium.chrome.browser.media.router.cast.MediaSource; import javax.annotation.Nullable; @@ -22,11 +23,45 @@ */ public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogManager { + /** + * A helper class to handle the system visibility change caused by the dialog showing up. + * Call saveSystemVisibility() in onCreateDialog() of the DialogFragment and later + * restoreSystemVisibility() in onStop(). + * TODO(avayvod): refactor this to avoid a redundant copy in ChromeMediaRouteDialogFactory. + */ + protected static class SystemVisibilitySaver { + private int mSystemVisibilityToRestore; + private boolean mWasFullscreenBeforeShowing; + + void saveSystemVisibility(Activity activity) { + // If we are in fullscreen we may have also have hidden the system UI. This + // is overridden when we display the dialog. Save the system UI visibility + // state so we can restore it. + FrameLayout decor = (FrameLayout) activity.getWindow().getDecorView(); + mSystemVisibilityToRestore = decor.getSystemUiVisibility(); + mWasFullscreenBeforeShowing = ( + (mSystemVisibilityToRestore & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0); + } + + void restoreSystemVisibility(Activity activity) { + if (!mWasFullscreenBeforeShowing) return; + + FrameLayout decor = (FrameLayout) activity.getWindow().getDecorView(); + // In some cases we come out of fullscreen before closing this dialog. In these + // cases we don't want to restore the system UI visibility state. + boolean isStillFullscreen = + (decor.getSystemUiVisibility() & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0; + if (!isStillFullscreen) return; + + decor.setSystemUiVisibility(mSystemVisibilityToRestore); + } + } + private final MediaSource mMediaSource; private final MediaRouter mAndroidMediaRouter; private final MediaRouteDialogDelegate mDelegate; - private DialogFragment mDialogFragment; + protected DialogFragment mDialogFragment; @Override public void openDialog() { @@ -39,8 +74,7 @@ FragmentManager fm = currentActivity.getSupportFragmentManager(); if (fm == null) return; - MediaRouteDialogFactory factory = new ChromeMediaRouteDialogFactory(); - mDialogFragment = openDialogInternal(fm, factory); + mDialogFragment = openDialogInternal(fm); } @Override @@ -68,12 +102,10 @@ * needed. * * @param fm {@link FragmentManager} to use to show the dialog. - * @param factory {@link MediaRouteDialogFactory} to use to create the dialog. * @return null if the initialization fails, otherwise the initialized dialog fragment. */ @Nullable - protected abstract DialogFragment openDialogInternal( - FragmentManager fm, MediaRouteDialogFactory factory); + protected abstract DialogFragment openDialogInternal(FragmentManager fm); protected MediaRouteDialogDelegate delegate() { return mDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java index d294354e..4d21c7d9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java
@@ -104,6 +104,12 @@ @Override public void onDialogCancelled() { + // For MediaRouteControllerDialog this method will be called in case the route is closed + // since it only call onDismiss() and there's no way to distinguish between the two. + // Here we can figure it out: if mDialogManager is null, onRouteClosed() was called and + // there's no need to tell the native controller the dialog has been cancelled. + if (mDialogManager == null) return; + mDialogManager = null; nativeOnDialogCancelled(mNativeDialogController); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java index 9bc3114..e7d190d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java
@@ -4,15 +4,11 @@ package org.chromium.chrome.browser.media.router; -import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnDismissListener; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.MediaRouteChooserDialogFragment; -import android.support.v7.app.MediaRouteDialogFactory; import org.chromium.chrome.browser.media.router.cast.MediaSink; import org.chromium.chrome.browser.media.router.cast.MediaSource; @@ -20,8 +16,7 @@ /** * Manages the dialog responsible for selecting a {@link MediaSink}. */ -public class MediaRouteChooserDialogManager extends BaseMediaRouteDialogManager implements - OnCancelListener, OnDismissListener { +public class MediaRouteChooserDialogManager extends BaseMediaRouteDialogManager { private static final String DIALOG_FRAGMENT_TAG = "android.support.v7.mediarouter:MediaRouteChooserDialogFragment"; @@ -34,39 +29,50 @@ } @Override - protected DialogFragment openDialogInternal(FragmentManager fm, - MediaRouteDialogFactory factory) { + protected DialogFragment openDialogInternal(FragmentManager fm) { if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null; - MediaRouteChooserDialogFragment fragment = factory.onCreateChooserDialogFragment(); + MediaRouteChooserDialogFragment fragment = new MediaRouteChooserDialogFragment() { + final SystemVisibilitySaver mVisibilitySaver = new SystemVisibilitySaver(); + + @Override + public void onStart() { + mVisibilitySaver.saveSystemVisibility(getActivity()); + super.onStart(); + } + + @Override + public void onStop() { + super.onStop(); + mVisibilitySaver.restoreSystemVisibility(getActivity()); + } + + @Override + public void onCancel(DialogInterface dialog) { + mCancelled = true; + + delegate().onDialogCancelled(); + + super.onCancel(dialog); + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + + mDialogFragment = null; + + if (mCancelled) return; + + MediaSink newSink = MediaSink.fromRoute(androidMediaRouter().getSelectedRoute()); + delegate().onSinkSelected(newSink); + } + }; + fragment.setRouteSelector(mediaSource().buildRouteSelector()); fragment.show(fm, DIALOG_FRAGMENT_TAG); fm.executePendingTransactions(); - Dialog dialog = fragment.getDialog(); - if (dialog == null) return null; - - dialog.setOnCancelListener(this); - dialog.setOnDismissListener(this); - return fragment; } - - @Override - public void onCancel(DialogInterface dialog) { - mCancelled = true; - - delegate().onDialogCancelled(); - } - - @Override - public void onDismiss(DialogInterface dialog) { - closeDialog(); - - if (mCancelled) return; - - MediaSink newSink = MediaSink.fromRoute(androidMediaRouter().getSelectedRoute()); - delegate().onSinkSelected(newSink); - } - }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java index c65ab4ea..91b11d2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java
@@ -4,15 +4,11 @@ package org.chromium.chrome.browser.media.router; -import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnDismissListener; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.MediaRouteControllerDialogFragment; -import android.support.v7.app.MediaRouteDialogFactory; import android.support.v7.media.MediaRouter; import org.chromium.chrome.browser.media.router.cast.MediaSource; @@ -20,13 +16,13 @@ /** * Manages the dialog responsible for controlling an existing media route. */ -public class MediaRouteControllerDialogManager extends BaseMediaRouteDialogManager implements - OnCancelListener, OnDismissListener { +public class MediaRouteControllerDialogManager extends BaseMediaRouteDialogManager { private static final String DIALOG_FRAGMENT_TAG = "android.support.v7.mediarouter:MediaRouteControllerDialogFragment"; private final String mMediaRouteId; + private final MediaRouter.Callback mCallback = new MediaRouter.Callback() { @Override public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) { @@ -42,32 +38,38 @@ } @Override - protected DialogFragment openDialogInternal(FragmentManager fm, - MediaRouteDialogFactory factory) { + protected DialogFragment openDialogInternal(FragmentManager fm) { if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null; - MediaRouteControllerDialogFragment fragment = factory.onCreateControllerDialogFragment(); + MediaRouteControllerDialogFragment fragment = new MediaRouteControllerDialogFragment() { + final SystemVisibilitySaver mVisibilitySaver = new SystemVisibilitySaver(); + + @Override + public void onStart() { + mVisibilitySaver.saveSystemVisibility(getActivity()); + super.onStart(); + } + + @Override + public void onStop() { + super.onStop(); + mVisibilitySaver.restoreSystemVisibility(getActivity()); + } + + @Override + public void onDismiss(DialogInterface dialog) { + delegate().onDialogCancelled(); + androidMediaRouter().removeCallback(mCallback); + mDialogFragment = null; + super.onDismiss(dialog); + } + }; + fragment.show(fm, DIALOG_FRAGMENT_TAG); fm.executePendingTransactions(); - Dialog dialog = fragment.getDialog(); - if (dialog == null) return null; - - dialog.setOnCancelListener(this); - dialog.setOnDismissListener(this); androidMediaRouter().addCallback(mediaSource().buildRouteSelector(), mCallback); return fragment; } - - @Override - public void onCancel(DialogInterface dialog) { - delegate().onDialogCancelled(); - } - - @Override - public void onDismiss(DialogInterface dialog) { - androidMediaRouter().removeCallback(mCallback); - closeDialog(); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java index 7fff8c24b..4bd5637 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PwsClient.java
@@ -78,11 +78,9 @@ private static Collection<PwsResult> parseResolveScanResponse(JSONObject result) { // Get the metadata array. Collection<PwsResult> pwsResults = new ArrayList<>(); - JSONArray metadata; - try { - metadata = result.getJSONArray("results"); - } catch (JSONException e) { - Log.e(TAG, "PWS returned invalid data", e); + JSONArray metadata = result.optJSONArray("results"); + if (metadata == null) { + // There are no valid results. return pwsResults; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java index 3d06bf9e..3078f9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.tab; +import android.graphics.Bitmap; import android.view.ContextMenu; import org.chromium.content.browser.ContentViewCore; @@ -49,7 +50,7 @@ public void onPageLoadFailed(Tab tab, int errorCode) { } @Override - public void onFaviconUpdated(Tab tab) { } + public void onFaviconUpdated(Tab tab, Bitmap icon) { } @Override public void onTitleUpdated(Tab tab) { }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index 309d49f..502f24c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -1086,8 +1086,19 @@ * on both cold and warm starts. */ public void onActivityStart() { + onActivityStartInternal(true); + } + + /** + * Called on the foreground tab when the Activity showing the Tab gets stopped. + */ + public void onActivityStop() { + hide(); + } + + protected void onActivityStartInternal(boolean showNow) { if (isHidden()) { - show(TabSelectionType.FROM_USER); + if (showNow) show(TabSelectionType.FROM_USER); } else { // The visible Tab's renderer process may have died after the activity was paused. // Ensure that it's restored appropriately. @@ -1101,13 +1112,6 @@ } /** - * Called on the foreground tab when the Activity showing the Tab gets stopped. - */ - public void onActivityStop() { - hide(); - } - - /** * @return Whether the tab is ready to display or it should be faded in as it loads. */ public boolean shouldStall() { @@ -1806,7 +1810,7 @@ private void notifyFaviconChanged() { RewindableIterator<TabObserver> observers = getTabObservers(); while (observers.hasNext()) { - observers.next().onFaviconUpdated(this); + observers.next().onFaviconUpdated(this, null); } } @@ -2088,7 +2092,6 @@ @CalledByNative protected void onFaviconAvailable(Bitmap icon) { - boolean needUpdate = false; String url = getUrl(); boolean pageUrlChanged = !url.equals(mFaviconUrl); // This method will be called multiple times if the page has more than one favicon. @@ -2097,17 +2100,10 @@ if (pageUrlChanged || (icon.getWidth() == mIdealFaviconSize && icon.getHeight() == mIdealFaviconSize)) { mFavicon = Bitmap.createScaledBitmap(icon, mIdealFaviconSize, mIdealFaviconSize, true); - needUpdate = true; - } - - if (pageUrlChanged) { mFaviconUrl = url; - needUpdate = true; } - if (!needUpdate) return; - - for (TabObserver observer : mObservers) observer.onFaviconUpdated(this); + for (TabObserver observer : mObservers) observer.onFaviconUpdated(this, icon); } /** * Called when the navigation entry containing the history item changed,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java index 168fc12..20a69d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.tab; +import android.graphics.Bitmap; import android.view.ContextMenu; import org.chromium.chrome.browser.TabLoadStatus; @@ -108,8 +109,9 @@ /** * Called when the favicon of a {@link Tab} has been updated. * @param tab The notifying {@link Tab}. + * @param icon The favicon that was received. */ - void onFaviconUpdated(Tab tab); + void onFaviconUpdated(Tab tab, Bitmap icon); /** * Called when the title of a {@link Tab} changes.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java index 5865b09..755c9df 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -6,7 +6,6 @@ import android.content.Context; import android.graphics.Color; -import android.support.annotation.IntDef; import android.view.View; import org.chromium.base.ActivityState; @@ -45,24 +44,6 @@ private static final int TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_BACKGROUND_APP = 2; private static final int TAB_RENDERER_CRASH_STATUS_MAX = 3; - // TabRendererExitStatus defined in tools/metrics/histograms/histograms.xml. - // Designed to replace TabRendererCrashStatus if numbers line up. - @IntDef({TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_RUNNING_APP, - TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_PAUSED_APP, - TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_BACKGROUND_APP, - TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_RUNNING_APP, - TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_PAUSED_APP, - TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_BACKGROUND_APP, - TAB_RENDERER_EXIT_STATUS_MAX}) - private @interface TabRendererExitStatus {} - private static final int TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_RUNNING_APP = 0; - private static final int TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_PAUSED_APP = 1; - private static final int TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_BACKGROUND_APP = 2; - private static final int TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_RUNNING_APP = 3; - private static final int TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_PAUSED_APP = 4; - private static final int TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_BACKGROUND_APP = 5; - private static final int TAB_RENDERER_EXIT_STATUS_MAX = 6; - private final Tab mTab; private int mThemeColor; @@ -86,31 +67,6 @@ // potential background tabs that did not reload yet). if (mTab.needsReload() || mTab.isShowingSadTab()) return; - // This will replace TabRendererCrashStatus if numbers line up. - int appState = ApplicationStatus.getStateForApplication(); - boolean applicationRunning = (appState == ApplicationState.HAS_RUNNING_ACTIVITIES); - boolean applicationPaused = (appState == ApplicationState.HAS_PAUSED_ACTIVITIES); - @TabRendererExitStatus int rendererExitStatus = TAB_RENDERER_EXIT_STATUS_MAX; - if (processWasOomProtected) { - if (applicationRunning) { - rendererExitStatus = TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_RUNNING_APP; - } else if (applicationPaused) { - rendererExitStatus = TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_PAUSED_APP; - } else { - rendererExitStatus = TAB_RENDERER_EXIT_STATUS_OOM_PROTECTED_IN_BACKGROUND_APP; - } - } else { - if (applicationRunning) { - rendererExitStatus = TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_RUNNING_APP; - } else if (applicationPaused) { - rendererExitStatus = TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_PAUSED_APP; - } else { - rendererExitStatus = TAB_RENDERER_EXIT_STATUS_NOT_PROTECTED_IN_BACKGROUND_APP; - } - } - RecordHistogram.recordEnumeratedHistogram( - "Tab.RendererExitStatus", rendererExitStatus, TAB_RENDERER_EXIT_STATUS_MAX); - int activityState = ApplicationStatus.getStateForActivity( mTab.getWindowAndroid().getActivity().get()); int rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_MAX; @@ -121,7 +77,8 @@ // The tab crashed in background or was killed by the OS out-of-memory killer. //setNeedsReload(true); mTab.setNeedsReload(true); - if (applicationRunning) { + if (ApplicationStatus.getStateForApplication() + == ApplicationState.HAS_RUNNING_ACTIVITIES) { rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_FOREGROUND_APP; } else { rendererCrashStatus = TAB_RENDERER_CRASH_STATUS_HIDDEN_IN_BACKGROUND_APP;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 3a3992b..7ebc2da 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -63,6 +63,8 @@ private WebappUma mWebappUma; + private Bitmap mLargestFavicon; + /** * Construct all the variables that shouldn't change. We do it here both to clarify when the * objects are created and to ensure that they exist throughout the parallelized initialization @@ -287,6 +289,7 @@ protected TabObserver createTabObserver() { return new EmptyTabObserver() { + @Override public void onSSLStateUpdated(Tab tab) { updateUrlBar(); @@ -313,9 +316,15 @@ } @Override - public void onFaviconUpdated(Tab tab) { + public void onFaviconUpdated(Tab tab, Bitmap icon) { if (!isWebappDomain()) return; - updateTaskDescription(); + // No need to cache the favicon if there is an icon declared in app manifest. + if (mWebappInfo.icon() != null) return; + if (mLargestFavicon == null || icon.getWidth() > mLargestFavicon.getWidth() + || icon.getHeight() > mLargestFavicon.getHeight()) { + mLargestFavicon = icon; + updateTaskDescription(); + } } @Override @@ -391,7 +400,7 @@ if (mWebappInfo.icon() != null) { icon = mWebappInfo.icon(); } else if (getActivityTab() != null) { - icon = getActivityTab().getFavicon(); + icon = mLargestFavicon; } if (mBrandColor == null && mWebappInfo.hasValidThemeColor()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java index 7fe59b31..a6812fc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
@@ -345,7 +345,7 @@ private final TabObserver mTabObserver = new EmptyTabObserver() { @Override - public void onFaviconUpdated(Tab tab) { + public void onFaviconUpdated(Tab tab, Bitmap icon) { updateFavicon(); notifyTabUpdated(tab); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index 78e8c44..15a6814 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -2585,4 +2585,51 @@ // Make sure we did not try to trigger translate. assertFalse(mManager.getRequest().isTranslationForced()); } + + /** + * Tests that a long-press does trigger translation. + */ + @SmallTest + @Feature({"ContextualSearch"}) + @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) + public void testLongpressTranslates() throws InterruptedException, TimeoutException { + // LongPress on any word should trigger translation. + simulateLongPressSearch("search"); + + // Make sure we did try to trigger translate. + assertTrue(mManager.getRequest().isTranslationForced()); + } + + /** + * Tests that a long-press does trigger translation. + */ + @SmallTest + @Feature({"ContextualSearch"}) + @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) + @CommandLineFlags.Add(ContextualSearchFieldTrial.DISABLE_AUTO_DETECT_TRANSLATION_ONEBOX + + "=true") + public void testLongpressAutoDetectDisabledDoesNotTranslate() + throws InterruptedException, TimeoutException { + // Unless disabled, LongPress on any word should trigger translation. + simulateLongPressSearch("search"); + + // Make sure we did not try to trigger translate. + assertFalse(mManager.getRequest().isTranslationForced()); + } + + /** + * Tests that a long-press does trigger translation. + */ + @SmallTest + @Feature({"ContextualSearch"}) + @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) + @CommandLineFlags.Add(ContextualSearchFieldTrial.DISABLE_FORCE_TRANSLATION_ONEBOX + "=true") + public void testLongpressTranslateDisabledDoesNotTranslate() + throws InterruptedException, TimeoutException { + // Unless disabled, LongPress on any word should trigger translation. + simulateLongPressSearch("search"); + + // Make sure we did not try to trigger translate. + assertFalse(mManager.getRequest().isTranslationForced()); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java new file mode 100644 index 0000000..0a7d394a --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java
@@ -0,0 +1,194 @@ +// Copyright 2015 The Chromium 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.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; +import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; +import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContent; +import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager; +import org.chromium.chrome.browser.compositor.bottombar.readermode.ReaderModeBarControl; +import org.chromium.chrome.browser.compositor.bottombar.readermode.ReaderModePanel; +import org.chromium.chrome.browser.compositor.scene_layer.ContextualSearchSceneLayer; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.test.util.browser.tabmodel.MockTabModel.MockTabModelDelegate; +import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector; +import org.chromium.content_public.browser.WebContents; +import org.chromium.content_public.browser.WebContentsObserver; + +/** + * Tests logic in the ReaderModeManager. + */ +public class ReaderModeManagerTest extends InstrumentationTestCase { + + MockOverlayPanelManager mPanelManager; + ReaderModeManagerWrapper mReaderManager; + MockReaderModePanel mPanel; + + /** + * A mock TabModelSelector for creating tabs. + */ + private static class ReaderModeMockTabModelSelector extends MockTabModelSelector { + public ReaderModeMockTabModelSelector() { + super(2, 0, + new MockTabModelDelegate() { + @Override + public Tab createTab(int id, boolean incognito) { + return new Tab(id, incognito, null); + } + }); + } + } + + /** + * Mock OverlayPanelManager for recording but not actually performing events. This will also + * detect calls to show/hide panel that do not pass through the ReaderModeManager's methods. + */ + private static class MockOverlayPanelManager extends OverlayPanelManager { + private int mRequestPanelShowCount; + private int mPanelHideCount; + + @Override + public void requestPanelShow(OverlayPanel p, StateChangeReason r) { + mRequestPanelShowCount++; + } + + @Override + public void notifyPanelClosed(OverlayPanel p, StateChangeReason r) { + mPanelHideCount++; + } + + public int getRequestPanelShowCount() { + return mRequestPanelShowCount; + } + + public int getPanelHideCount() { + return mPanelHideCount; + } + } + + /** + * A wrapper for the ReaderModeManager; this is used for recording and triggering events + * manually. + */ + private static class ReaderModeManagerWrapper extends ReaderModeManager { + public ReaderModeManagerWrapper() { + super(new ReaderModeMockTabModelSelector(), null); + } + + @Override + protected void requestReaderPanelShow(StateChangeReason reason) { + // Skip tab checks and request the panel be shown. + mReaderModePanel.requestPanelShow(reason); + } + + @Override + public WebContentsObserver createWebContentsObserver(WebContents webContents) { + // Do not attempt to create or attach a WebContentsObserver. + return null; + } + } + + /** + * Mock ReaderModePanel. + */ + private static class MockReaderModePanel extends ReaderModePanel { + public MockReaderModePanel(Context context, OverlayPanelManager manager) { + super(context, null, manager, null); + } + + @Override + public ContextualSearchSceneLayer createNewReaderModeSceneLayer() { + return null; + } + + @Override + protected ReaderModeBarControl getReaderModeBarControl() { + return new MockReaderModeBarControl(); + } + + /** + * This class is overridden to be completely inert; it would otherwise call many native + * methods. + */ + private static class MockReaderModeBarControl extends ReaderModeBarControl { + public MockReaderModeBarControl() { + super(null, null, null, null); + } + + @Override + public void setBarText(int stringId) {} + + @Override + public void inflate() {} + + @Override + public void invalidate() {} + } + + /** + * Override creation and destruction of the ContentViewCore as they rely on native methods. + */ + private static class MockOverlayPanelContent extends OverlayPanelContent { + public MockOverlayPanelContent() { + super(null, null, null); + } + + @Override + public void removeLastHistoryEntry(String url, long timeInMs) {} + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mPanelManager = new MockOverlayPanelManager(); + mReaderManager = new ReaderModeManagerWrapper(); + mPanel = new MockReaderModePanel(getInstrumentation().getTargetContext(), mPanelManager); + mReaderManager.setReaderModePanel(mPanel); + } + + // Start ReaderModeManager test suite. + + /** + * Tests that the panel behaves appropriately with infobar events. + */ + @SmallTest + @Feature({"ReaderModeManager"}) + public void testInfoBarEvents() { + mReaderManager.onAddInfoBar(null, null, true); + assertEquals(0, mPanelManager.getRequestPanelShowCount()); + assertEquals(1, mPanelManager.getPanelHideCount()); + + mReaderManager.onRemoveInfoBar(null, null, true); + assertEquals(1, mPanelManager.getRequestPanelShowCount()); + assertEquals(1, mPanelManager.getPanelHideCount()); + } + + /** + * Tests that the panel behaves appropriately with fullscreen events. + */ + @SmallTest + @Feature({"ReaderModeManager"}) + public void testFullscreenEvents() { + mReaderManager.onToggleFullscreenMode(null, true); + assertEquals(0, mPanelManager.getRequestPanelShowCount()); + assertEquals(1, mPanelManager.getPanelHideCount()); + + mReaderManager.onToggleFullscreenMode(null, false); + assertEquals(1, mPanelManager.getRequestPanelShowCount()); + assertEquals(1, mPanelManager.getPanelHideCount()); + } + + // TODO(mdjones): Test add/remove infobar while fullscreen is enabled. + // TODO(mdjones): Test onclosebuttonpressed disables Reader Mode for a particular tab. + // TODO(mdjones): Test onorientationchanged closes and re-opens panel. + // TODO(mdjones): Test tab events. + // TODO(mdjones): Test distillability callback. +}
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index f435a6c..5ddd25e 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -3624,6 +3624,9 @@ <message name="IDS_TASK_MANAGER_UNKNOWN_VALUE_TEXT" desc="The value displayed for an unknown NaCl debug stub port in the task manager."> Unknown </message> + <message name="IDS_TASK_MANAGER_DISABLED_NACL_DBG_TEXT" desc="The value displayed for NaCl debug stub port in the task manager when the flag #enable-nacl-debug is disabled."> + Disabled + </message> <message name="IDS_TASK_MANAGER_HANDLES_CELL_TEXT" desc="The value displayed in the user/gdi cells."> <ph name="NUM_HANDLES">$1<ex>300</ex></ph> (<ph name="NUM_KILOBYTES_LIVE">$2<ex>500</ex></ph> peak) </message> @@ -6040,9 +6043,11 @@ <message name="IDS_PASSWORD_MANAGER_SMART_LOCK_WELCOME" desc="A warm welcome message displayed once in the Save password bubble for users which are signed-in to Chrome."> Smart Lock helps you quickly sign in to apps and sites using passwords you have saved with Google. </message> - <message name="IDS_PASSWORD_MANAGER_SMART_LOCK_PAGE" desc="URL of the passwords dashboard."> - https://passwords.google.com/?hl=[GRITLANGCODE] - </message> + <if expr="is_android"> + <message name="IDS_PASSWORD_MANAGER_SMART_LOCK_PAGE" desc="URL of the passwords dashboard."> + https://passwords.google.com/?hl=[GRITLANGCODE] + </message> + </if> <message name="IDS_FLAGS_ENABLE_SUGGESTIONS_WITH_SUB_STRING_MATCH_NAME" desc="Name of the flag to enable substring matching for Autofill suggestions."> Substring matching for Autofill suggestions. </message> @@ -8832,9 +8837,12 @@ </message> </if> <if expr="is_android"> - <message name="IDS_ERRORPAGES_BUTTON_SHOW_SAVED_PAGES" desc="Label for the button on an error page to show pages that have been saved offline"> + <message name="IDS_ERRORPAGES_BUTTON_SHOW_OFFLINE_PAGES" desc="Label for the button on an error page to show pages that have been saved offline"> Show all saved pages </message> + <message name="IDS_ERRORPAGES_BUTTON_SHOW_OFFLINE_COPY" desc="Label for the button on an error page to show the copy of this page that has been saved offline"> + Show saved copy + </message> </if> <message name="IDS_ERRORPAGE_FUN_DISABLED" desc="Explanation for when easter egg has been disabled by administrator"> The owner of this device turned off the dinosaur game. @@ -12852,6 +12860,12 @@ <message name="IDS_SHOW_DOWNLOADS_MAC" desc="The Mac menu item to show downloads in the window menu."> Downloads </message> + <message name="IDS_WINDOW_AUDIO_PLAYING_MAC" desc="The emoji to append to the title of a window showing audio is playing."> + <ph name="TAB_TITLE">$1<ex>The Title of the Tab</ex></ph> <ph name="EMOJI_PLAYING">$2<ex>(playing)</ex></ph> + </message> + <message name="IDS_WINDOW_AUDIO_MUTING_MAC" desc="The emoji to append to the title of a window showing audio is muting."> + <ph name="TAB_TITLE">$1<ex>The Title of the Tab</ex></ph> <ph name="EMOJI_MUTING">$2<ex>(muting)</ex></ph> + </message> <message name="IDS_SHOW_EXTENSIONS_MAC" desc="The Mac menu item to show extensions in the window menu."> Extensions </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f93e73b..8f19496 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -90,7 +90,6 @@ "//sync", ] deps = [ - "//base/allocator", "//chrome:extra_resources", "//chrome:resources", "//chrome:strings",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index e2ff266..cac5aec 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -9,6 +9,8 @@ #include <set> #include <utility> +#include "base/bind.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/feature_list.h" #include "base/memory/singleton.h" @@ -33,6 +35,7 @@ #include "components/enhanced_bookmarks/enhanced_bookmark_switches.h" #include "components/flags_ui/feature_entry_macros.h" #include "components/flags_ui/flags_storage.h" +#include "components/flags_ui/flags_ui_switches.h" #include "components/metrics/metrics_hashes.h" #include "components/nacl/common/nacl_switches.h" #include "components/offline_pages/offline_page_switches.h" @@ -90,77 +93,20 @@ #endif using flags_ui::FeatureEntry; +using flags_ui::kOsMac; +using flags_ui::kOsWin; +using flags_ui::kOsLinux; +using flags_ui::kOsCrOS; +using flags_ui::kOsAndroid; +using flags_ui::kOsCrOSOwnerOnly; namespace about_flags { namespace { -// Enumeration of OSs. -enum { - kOsMac = 1 << 0, - kOsWin = 1 << 1, - kOsLinux = 1 << 2, - kOsCrOS = 1 << 3, - kOsAndroid = 1 << 4, - kOsCrOSOwnerOnly = 1 << 5 -}; - const unsigned kOsAll = kOsMac | kOsWin | kOsLinux | kOsCrOS | kOsAndroid; const unsigned kOsDesktop = kOsMac | kOsWin | kOsLinux | kOsCrOS; -// Adds a |StringValue| to |list| for each platform where |bitmask| indicates -// whether the entry is available on that platform. -void AddOsStrings(unsigned bitmask, base::ListValue* list) { - struct { - unsigned bit; - const char* const name; - } kBitsToOs[] = { - {kOsMac, "Mac"}, - {kOsWin, "Windows"}, - {kOsLinux, "Linux"}, - {kOsCrOS, "Chrome OS"}, - {kOsAndroid, "Android"}, - {kOsCrOSOwnerOnly, "Chrome OS (owner only)"}, - }; - for (size_t i = 0; i < arraysize(kBitsToOs); ++i) { - if (bitmask & kBitsToOs[i].bit) - list->Append(new base::StringValue(kBitsToOs[i].name)); - } -} - -// Convert switch constants to proper CommandLine::StringType strings. -base::CommandLine::StringType GetSwitchString(const std::string& flag) { - base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM); - cmd_line.AppendSwitch(flag); - DCHECK_EQ(2U, cmd_line.argv().size()); - return cmd_line.argv()[1]; -} - -// Scoops flags from a command line. -std::set<base::CommandLine::StringType> ExtractFlagsFromCommandLine( - const base::CommandLine& cmdline) { - std::set<base::CommandLine::StringType> flags; - // First do the ones between --flag-switches-begin and --flag-switches-end. - base::CommandLine::StringVector::const_iterator first = - std::find(cmdline.argv().begin(), cmdline.argv().end(), - GetSwitchString(switches::kFlagSwitchesBegin)); - base::CommandLine::StringVector::const_iterator last = - std::find(cmdline.argv().begin(), cmdline.argv().end(), - GetSwitchString(switches::kFlagSwitchesEnd)); - if (first != cmdline.argv().end() && last != cmdline.argv().end()) - flags.insert(first + 1, last); -#if defined(OS_CHROMEOS) - // Then add those between --policy-switches-begin and --policy-switches-end. - first = std::find(cmdline.argv().begin(), cmdline.argv().end(), - GetSwitchString(chromeos::switches::kPolicySwitchesBegin)); - last = std::find(cmdline.argv().begin(), cmdline.argv().end(), - GetSwitchString(chromeos::switches::kPolicySwitchesEnd)); - if (first != cmdline.argv().end() && last != cmdline.argv().end()) - flags.insert(first + 1, last); -#endif - return flags; -} - const FeatureEntry::Choice kTouchEventsChoices[] = { { IDS_GENERIC_EXPERIMENT_CHOICE_AUTOMATIC, "", "" }, { IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED, @@ -2112,193 +2058,28 @@ // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test. }; -// Stores and encapsulates the little state that about:flags has. -class FlagsState { +class FlagsStateSingleton { public: - FlagsState() - : feature_entries(kFeatureEntries), - num_feature_entries(arraysize(kFeatureEntries)), - needs_restart_(false) {} - void ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage, - base::CommandLine* command_line, - SentinelsMode sentinels); - bool IsRestartNeededToCommitChanges(); - void SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage, - const std::string& internal_name, - bool enable); - void RemoveFlagsSwitches( - std::map<std::string, base::CommandLine::StringType>* switch_list); - void ResetAllFlags(flags_ui::FlagsStorage* flags_storage); - void Reset(); + FlagsStateSingleton() + : flags_state_(kFeatureEntries, arraysize(kFeatureEntries)) {} + ~FlagsStateSingleton() {} - // Gets the list of feature entries. Entries that are available for the - // current platform are appended to |supported_entries|; all other entries are - // appended to |unsupported_entries|. - void GetFlagFeatureEntries(flags_ui::FlagsStorage* flags_storage, - FlagAccess access, - base::ListValue* supported_entries, - base::ListValue* unsupported_entries); + static FlagsStateSingleton* GetInstance() { + return base::Singleton<FlagsStateSingleton>::get(); + } - void SetFeatureEntries(const FeatureEntry* entries, size_t count); - const FeatureEntry* GetFeatureEntries(size_t* count); - - // Returns the singleton instance of this class - static FlagsState* GetInstance() { - return base::Singleton<FlagsState>::get(); + static flags_ui::FlagsState* GetFlagsState() { + return &GetInstance()->flags_state_; } private: - // Keeps track of affected switches for each FeatureEntry, based on which - // choice is selected for it. - struct SwitchEntry { - // Corresponding base::Feature to toggle. - std::string feature_name; + flags_ui::FlagsState flags_state_; - // If |feature_name| is not empty, the state (enable/disabled) to set. - bool feature_state; - - // The name of the switch to add. - std::string switch_name; - - // If |switch_name| is not empty, the value of the switch to set. - std::string switch_value; - - SwitchEntry() : feature_state(false) {} - }; - - // Adds mapping to |name_to_switch_map| to set the given switch name/value. - void AddSwitchMapping(const std::string& key, - const std::string& switch_name, - const std::string& switch_value, - std::map<std::string, SwitchEntry>* name_to_switch_map); - - // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name| - // to state |feature_state|. - void AddFeatureMapping( - const std::string& key, - const std::string& feature_name, - bool feature_state, - std::map<std::string, SwitchEntry>* name_to_switch_map); - - // Updates the switches in |command_line| by applying the modifications - // specified in |name_to_switch_map| for each entry in |enabled_entries|. - void AddSwitchesToCommandLine( - const std::set<std::string>& enabled_entries, - const std::map<std::string, SwitchEntry>& name_to_switch_map, - SentinelsMode sentinels, - base::CommandLine* command_line); - - // Updates |command_line| by merging the value of the --enable-features= or - // --disable-features= list (per the |switch_name| param) with corresponding - // entries in |feature_switches| that have value |feature_state|. Keeps track - // of the changes by updating |appended_switches|. - void MergeFeatureCommandLineSwitch( - const std::map<std::string, bool>& feature_switches, - const char* switch_name, - bool feature_state, - base::CommandLine* command_line); - - // Removes all entries from prefs::kEnabledLabsExperiments that are unknown, - // to prevent this list to become very long as entries are added and removed. - void SanitizeList(flags_ui::FlagsStorage* flags_storage); - - void GetSanitizedEnabledFlags(flags_ui::FlagsStorage* flags_storage, - std::set<std::string>* result); - - // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't - // enabled on the current platform. - void GetSanitizedEnabledFlagsForCurrentPlatform( - flags_ui::FlagsStorage* flags_storage, - std::set<std::string>* result); - - const FeatureEntry* feature_entries; - size_t num_feature_entries; - - bool needs_restart_; - std::map<std::string, std::string> flags_switches_; - - // Map from switch name to a set of string, that keeps track which strings - // were appended to existing (list value) switches. - std::map<std::string, std::set<std::string>> appended_switches_; - - DISALLOW_COPY_AND_ASSIGN(FlagsState); + DISALLOW_COPY_AND_ASSIGN(FlagsStateSingleton); }; -// Adds the internal names for the specified entry to |names|. -void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) { - switch (e.type) { - case FeatureEntry::SINGLE_VALUE: - case FeatureEntry::SINGLE_DISABLE_VALUE: - names->insert(e.internal_name); - break; - case FeatureEntry::MULTI_VALUE: - case FeatureEntry::ENABLE_DISABLE_VALUE: - case FeatureEntry::FEATURE_VALUE: - for (int i = 0; i < e.num_choices; ++i) - names->insert(e.NameForChoice(i)); - break; - } -} - -// Confirms that an entry is valid, used in a DCHECK in -// SanitizeList below. -bool ValidateFeatureEntry(const FeatureEntry& e) { - switch (e.type) { - case FeatureEntry::SINGLE_VALUE: - case FeatureEntry::SINGLE_DISABLE_VALUE: - DCHECK_EQ(0, e.num_choices); - DCHECK(!e.choices); - return true; - case FeatureEntry::MULTI_VALUE: - DCHECK_GT(e.num_choices, 0); - DCHECK(e.choices); - DCHECK(e.choices[0].command_line_switch); - DCHECK_EQ('\0', e.choices[0].command_line_switch[0]); - return true; - case FeatureEntry::ENABLE_DISABLE_VALUE: - DCHECK_EQ(3, e.num_choices); - DCHECK(!e.choices); - DCHECK(e.command_line_switch); - DCHECK(e.command_line_value); - DCHECK(e.disable_command_line_switch); - DCHECK(e.disable_command_line_value); - return true; - case FeatureEntry::FEATURE_VALUE: - DCHECK_EQ(3, e.num_choices); - DCHECK(!e.choices); - DCHECK(e.feature); - return true; - } - NOTREACHED(); - return false; -} - -void FlagsState::SanitizeList(flags_ui::FlagsStorage* flags_storage) { - std::set<std::string> known_entries; - for (size_t i = 0; i < num_feature_entries; ++i) { - DCHECK(ValidateFeatureEntry(feature_entries[i])); - AddInternalName(feature_entries[i], &known_entries); - } - - std::set<std::string> enabled_entries = flags_storage->GetFlags(); - - std::set<std::string> new_enabled_entries = - base::STLSetIntersection<std::set<std::string> >( - known_entries, enabled_entries); - - if (new_enabled_entries != enabled_entries) - flags_storage->SetFlags(new_enabled_entries); -} - -void FlagsState::GetSanitizedEnabledFlags(flags_ui::FlagsStorage* flags_storage, - std::set<std::string>* result) { - SanitizeList(flags_storage); - *result = flags_storage->GetFlags(); -} - bool SkipConditionalFeatureEntry(const FeatureEntry& entry) { version_info::Channel channel = chrome::GetChannel(); - #if defined(OS_ANDROID) // enable-data-reduction-proxy-dev is only available for the Dev/Beta channel. if (!strcmp("enable-data-reduction-proxy-dev", entry.internal_name) && @@ -2357,214 +2138,64 @@ return false; } -void FlagsState::GetSanitizedEnabledFlagsForCurrentPlatform( - flags_ui::FlagsStorage* flags_storage, - std::set<std::string>* result) { - GetSanitizedEnabledFlags(flags_storage, result); - - // Filter out any entries that aren't enabled on the current platform. We - // don't remove these from prefs else syncing to a platform with a different - // set of entries would be lossy. - std::set<std::string> platform_entries; - int current_platform = GetCurrentPlatform(); - for (size_t i = 0; i < num_feature_entries; ++i) { - const FeatureEntry& entry = feature_entries[i]; - if (entry.supported_platforms & current_platform) - AddInternalName(entry, &platform_entries); -#if defined(OS_CHROMEOS) - if (feature_entries[i].supported_platforms & kOsCrOSOwnerOnly) - AddInternalName(entry, &platform_entries); -#endif - } - - std::set<std::string> new_enabled_entries = - base::STLSetIntersection<std::set<std::string> >( - platform_entries, *result); - - result->swap(new_enabled_entries); -} - -// Returns true if none of this entry's options have been enabled. -bool IsDefaultValue( - const FeatureEntry& entry, - const std::set<std::string>& enabled_entries) { - switch (entry.type) { - case FeatureEntry::SINGLE_VALUE: - case FeatureEntry::SINGLE_DISABLE_VALUE: - return enabled_entries.count(entry.internal_name) == 0; - case FeatureEntry::MULTI_VALUE: - case FeatureEntry::ENABLE_DISABLE_VALUE: - case FeatureEntry::FEATURE_VALUE: - for (int i = 0; i < entry.num_choices; ++i) { - if (enabled_entries.count(entry.NameForChoice(i)) > 0) - return false; - } - return true; - } - NOTREACHED(); - return true; -} - -// Returns the Value representing the choice data in the specified entry. -base::Value* CreateChoiceData( - const FeatureEntry& entry, - const std::set<std::string>& enabled_entries) { - DCHECK(entry.type == FeatureEntry::MULTI_VALUE || - entry.type == FeatureEntry::ENABLE_DISABLE_VALUE || - entry.type == FeatureEntry::FEATURE_VALUE); - base::ListValue* result = new base::ListValue; - for (int i = 0; i < entry.num_choices; ++i) { - base::DictionaryValue* value = new base::DictionaryValue; - const std::string name = entry.NameForChoice(i); - value->SetString("internal_name", name); - value->SetString("description", entry.DescriptionForChoice(i)); - value->SetBoolean("selected", enabled_entries.count(name) > 0); - result->Append(value); - } - return result; -} - } // namespace void ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage, base::CommandLine* command_line, - SentinelsMode sentinels) { - FlagsState::GetInstance()->ConvertFlagsToSwitches(flags_storage, - command_line, - sentinels); + flags_ui::SentinelsMode sentinels) { + if (command_line->HasSwitch(switches::kNoExperiments)) + return; + + FlagsStateSingleton::GetFlagsState()->ConvertFlagsToSwitches( + flags_storage, command_line, sentinels, switches::kEnableFeatures, + switches::kDisableFeatures); } bool AreSwitchesIdenticalToCurrentCommandLine( const base::CommandLine& new_cmdline, const base::CommandLine& active_cmdline, std::set<base::CommandLine::StringType>* out_difference) { - std::set<base::CommandLine::StringType> new_flags = - ExtractFlagsFromCommandLine(new_cmdline); - std::set<base::CommandLine::StringType> active_flags = - ExtractFlagsFromCommandLine(active_cmdline); - - bool result = false; - // Needed because std::equal doesn't check if the 2nd set is empty. - if (new_flags.size() == active_flags.size()) { - result = - std::equal(new_flags.begin(), new_flags.end(), active_flags.begin()); - } - - if (out_difference && !result) { - std::set_symmetric_difference( - new_flags.begin(), - new_flags.end(), - active_flags.begin(), - active_flags.end(), - std::inserter(*out_difference, out_difference->begin())); - } - - return result; -} - -void FlagsState::GetFlagFeatureEntries(flags_ui::FlagsStorage* flags_storage, - FlagAccess access, - base::ListValue* supported_entries, - base::ListValue* unsupported_entries) { - std::set<std::string> enabled_entries; - GetSanitizedEnabledFlags(flags_storage, &enabled_entries); - - int current_platform = GetCurrentPlatform(); - - for (size_t i = 0; i < num_feature_entries; ++i) { - const FeatureEntry& entry = feature_entries[i]; - if (SkipConditionalFeatureEntry(entry)) - continue; - - base::DictionaryValue* data = new base::DictionaryValue(); - data->SetString("internal_name", entry.internal_name); - data->SetString("name", - l10n_util::GetStringUTF16(entry.visible_name_id)); - data->SetString("description", - l10n_util::GetStringUTF16( - entry.visible_description_id)); - - base::ListValue* supported_platforms = new base::ListValue(); - AddOsStrings(entry.supported_platforms, supported_platforms); - data->Set("supported_platforms", supported_platforms); - // True if the switch is not currently passed. - bool is_default_value = IsDefaultValue(entry, enabled_entries); - data->SetBoolean("is_default", is_default_value); - - switch (entry.type) { - case FeatureEntry::SINGLE_VALUE: - case FeatureEntry::SINGLE_DISABLE_VALUE: - data->SetBoolean( - "enabled", - (!is_default_value && - entry.type == FeatureEntry::SINGLE_VALUE) || - (is_default_value && - entry.type == FeatureEntry::SINGLE_DISABLE_VALUE)); - break; - case FeatureEntry::MULTI_VALUE: - case FeatureEntry::ENABLE_DISABLE_VALUE: - case FeatureEntry::FEATURE_VALUE: - data->Set("choices", CreateChoiceData(entry, enabled_entries)); - break; - } - - bool supported = (entry.supported_platforms & current_platform) != 0; + const char* extra_flag_sentinel_begin_flag_name = nullptr; + const char* extra_flag_sentinel_end_flag_name = nullptr; #if defined(OS_CHROMEOS) - if (access == kOwnerAccessToFlags && - (entry.supported_platforms & kOsCrOSOwnerOnly) != 0) { - supported = true; - } + // Put the flags between --policy-switches--begin and --policy-switches-end on + // ChromeOS. + extra_flag_sentinel_begin_flag_name = + chromeos::switches::kPolicySwitchesBegin; + extra_flag_sentinel_end_flag_name = chromeos::switches::kPolicySwitchesEnd; #endif - if (supported) - supported_entries->Append(data); - else - unsupported_entries->Append(data); - } + return flags_ui::FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + new_cmdline, active_cmdline, out_difference, + extra_flag_sentinel_begin_flag_name, extra_flag_sentinel_end_flag_name); } void GetFlagFeatureEntries(flags_ui::FlagsStorage* flags_storage, - FlagAccess access, + flags_ui::FlagAccess access, base::ListValue* supported_entries, base::ListValue* unsupported_entries) { - FlagsState::GetInstance()->GetFlagFeatureEntries(flags_storage, access, - supported_entries, - unsupported_entries); + FlagsStateSingleton::GetFlagsState()->GetFlagFeatureEntries( + flags_storage, access, supported_entries, unsupported_entries, + base::Bind(&SkipConditionalFeatureEntry)); } bool IsRestartNeededToCommitChanges() { - return FlagsState::GetInstance()->IsRestartNeededToCommitChanges(); + return FlagsStateSingleton::GetFlagsState()->IsRestartNeededToCommitChanges(); } void SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage, const std::string& internal_name, bool enable) { - FlagsState::GetInstance()->SetFeatureEntryEnabled(flags_storage, - internal_name, enable); + FlagsStateSingleton::GetFlagsState()->SetFeatureEntryEnabled( + flags_storage, internal_name, enable); } void RemoveFlagsSwitches( std::map<std::string, base::CommandLine::StringType>* switch_list) { - FlagsState::GetInstance()->RemoveFlagsSwitches(switch_list); + FlagsStateSingleton::GetFlagsState()->RemoveFlagsSwitches(switch_list); } void ResetAllFlags(flags_ui::FlagsStorage* flags_storage) { - FlagsState::GetInstance()->ResetAllFlags(flags_storage); -} - -int GetCurrentPlatform() { -#if defined(OS_MACOSX) - return kOsMac; -#elif defined(OS_WIN) - return kOsWin; -#elif defined(OS_CHROMEOS) // Needs to be before the OS_LINUX check. - return kOsCrOS; -#elif defined(OS_LINUX) || defined(OS_OPENBSD) - return kOsLinux; -#elif defined(OS_ANDROID) - return kOsAndroid; -#else -#error Unknown platform -#endif + FlagsStateSingleton::GetFlagsState()->ResetAllFlags(flags_storage); } void RecordUMAStatistics(flags_ui::FlagsStorage* flags_storage) { @@ -2613,310 +2244,13 @@ } } -////////////////////////////////////////////////////////////////////////////// -// FlagsState implementation. - -namespace { - -void FlagsState::ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage, - base::CommandLine* command_line, - SentinelsMode sentinels) { - if (command_line->HasSwitch(switches::kNoExperiments)) - return; - - std::set<std::string> enabled_entries; - - GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries); - - std::map<std::string, SwitchEntry> name_to_switch_map; - for (size_t i = 0; i < num_feature_entries; ++i) { - const FeatureEntry& e = feature_entries[i]; - switch (e.type) { - case FeatureEntry::SINGLE_VALUE: - case FeatureEntry::SINGLE_DISABLE_VALUE: - AddSwitchMapping(e.internal_name, e.command_line_switch, - e.command_line_value, &name_to_switch_map); - break; - case FeatureEntry::MULTI_VALUE: - for (int j = 0; j < e.num_choices; ++j) { - AddSwitchMapping(e.NameForChoice(j), e.choices[j].command_line_switch, - e.choices[j].command_line_value, - &name_to_switch_map); - } - break; - case FeatureEntry::ENABLE_DISABLE_VALUE: - AddSwitchMapping(e.NameForChoice(0), std::string(), std::string(), - &name_to_switch_map); - AddSwitchMapping(e.NameForChoice(1), e.command_line_switch, - e.command_line_value, &name_to_switch_map); - AddSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch, - e.disable_command_line_value, &name_to_switch_map); - break; - case FeatureEntry::FEATURE_VALUE: - AddFeatureMapping(e.NameForChoice(0), std::string(), false, - &name_to_switch_map); - AddFeatureMapping(e.NameForChoice(1), e.feature->name, true, - &name_to_switch_map); - AddFeatureMapping(e.NameForChoice(2), e.feature->name, false, - &name_to_switch_map); - break; - } - } - - AddSwitchesToCommandLine(enabled_entries, name_to_switch_map, sentinels, - command_line); -} - -bool FlagsState::IsRestartNeededToCommitChanges() { - return needs_restart_; -} - -void FlagsState::SetFeatureEntryEnabled(flags_ui::FlagsStorage* flags_storage, - const std::string& internal_name, - bool enable) { - size_t at_index = internal_name.find(flags_ui::testing::kMultiSeparator); - if (at_index != std::string::npos) { - DCHECK(enable); - // We're being asked to enable a multi-choice entry. Disable the - // currently selected choice. - DCHECK_NE(at_index, 0u); - const std::string entry_name = internal_name.substr(0, at_index); - SetFeatureEntryEnabled(flags_storage, entry_name, false); - - // And enable the new choice, if it is not the default first choice. - if (internal_name != entry_name + "@0") { - std::set<std::string> enabled_entries; - GetSanitizedEnabledFlags(flags_storage, &enabled_entries); - needs_restart_ |= enabled_entries.insert(internal_name).second; - flags_storage->SetFlags(enabled_entries); - } - return; - } - - std::set<std::string> enabled_entries; - GetSanitizedEnabledFlags(flags_storage, &enabled_entries); - - const FeatureEntry* e = nullptr; - for (size_t i = 0; i < num_feature_entries; ++i) { - if (feature_entries[i].internal_name == internal_name) { - e = feature_entries + i; - break; - } - } - DCHECK(e); - - if (e->type == FeatureEntry::SINGLE_VALUE) { - if (enable) - needs_restart_ |= enabled_entries.insert(internal_name).second; - else - needs_restart_ |= (enabled_entries.erase(internal_name) > 0); - } else if (e->type == FeatureEntry::SINGLE_DISABLE_VALUE) { - if (!enable) - needs_restart_ |= enabled_entries.insert(internal_name).second; - else - needs_restart_ |= (enabled_entries.erase(internal_name) > 0); - } else { - if (enable) { - // Enable the first choice. - needs_restart_ |= enabled_entries.insert(e->NameForChoice(0)).second; - } else { - // Find the currently enabled choice and disable it. - for (int i = 0; i < e->num_choices; ++i) { - std::string choice_name = e->NameForChoice(i); - if (enabled_entries.find(choice_name) != - enabled_entries.end()) { - needs_restart_ = true; - enabled_entries.erase(choice_name); - // Continue on just in case there's a bug and more than one - // entry for this choice was enabled. - } - } - } - } - - flags_storage->SetFlags(enabled_entries); -} - -void FlagsState::RemoveFlagsSwitches( - std::map<std::string, base::CommandLine::StringType>* switch_list) { - for (const auto& entry : flags_switches_) - switch_list->erase(entry.first); - - // If feature entries were added to --enable-features= or --disable-features= - // lists, remove them here while preserving existing values. - for (const auto& entry : appended_switches_) { - const auto& switch_name = entry.first; - const auto& switch_added_values = entry.second; - - // The below is either a std::string or a base::string16 based on platform. - const auto& existing_value = (*switch_list)[switch_name]; -#if defined(OS_WIN) - const std::string existing_value_utf8 = base::UTF16ToUTF8(existing_value); -#else - const std::string& existing_value_utf8 = existing_value; -#endif - - std::vector<std::string> features = - base::FeatureList::SplitFeatureListString(existing_value_utf8); - std::vector<std::string> remaining_features; - // For any featrue name in |features| that is not in |switch_added_values| - - // i.e. it wasn't added by about_flags code, add it to |remaining_features|. - for (const std::string& feature : features) { - if (!ContainsKey(switch_added_values, feature)) - remaining_features.push_back(feature); - } - - // Either remove the flag entirely if |remaining_features| is empty, or set - // the new list. - if (remaining_features.empty()) { - switch_list->erase(switch_name); - } else { - std::string switch_value = base::JoinString(remaining_features, ","); -#if defined(OS_WIN) - (*switch_list)[switch_name] = base::UTF8ToUTF16(switch_value); -#else - (*switch_list)[switch_name] = switch_value; -#endif - } - } -} - -void FlagsState::ResetAllFlags(flags_ui::FlagsStorage* flags_storage) { - needs_restart_ = true; - - std::set<std::string> no_entries; - flags_storage->SetFlags(no_entries); -} - -void FlagsState::Reset() { - needs_restart_ = false; - flags_switches_.clear(); - appended_switches_.clear(); -} - -void FlagsState::SetFeatureEntries(const FeatureEntry* entries, size_t count) { - feature_entries = entries; - num_feature_entries = count; -} - -const FeatureEntry* FlagsState::GetFeatureEntries(size_t* count) { - *count = num_feature_entries; - return feature_entries; -} - -void FlagsState::AddSwitchMapping( - const std::string& key, - const std::string& switch_name, - const std::string& switch_value, - std::map<std::string, SwitchEntry>* name_to_switch_map) { - DCHECK(!ContainsKey(*name_to_switch_map, key)); - - SwitchEntry* entry = &(*name_to_switch_map)[key]; - entry->switch_name = switch_name; - entry->switch_value = switch_value; -} - -void FlagsState::AddFeatureMapping( - const std::string& key, - const std::string& feature_name, - bool feature_state, - std::map<std::string, SwitchEntry>* name_to_switch_map) { - DCHECK(!ContainsKey(*name_to_switch_map, key)); - - SwitchEntry* entry = &(*name_to_switch_map)[key]; - entry->feature_name = feature_name; - entry->feature_state = feature_state; -} - -void FlagsState::AddSwitchesToCommandLine( - const std::set<std::string>& enabled_entries, - const std::map<std::string, SwitchEntry>& name_to_switch_map, - SentinelsMode sentinels, - base::CommandLine* command_line) { - std::map<std::string, bool> feature_switches; - if (sentinels == kAddSentinels) { - command_line->AppendSwitch(switches::kFlagSwitchesBegin); - flags_switches_[switches::kFlagSwitchesBegin] = std::string(); - } - - for (const std::string& entry_name : enabled_entries) { - const auto& entry_it = name_to_switch_map.find(entry_name); - if (entry_it == name_to_switch_map.end()) { - NOTREACHED(); - continue; - } - - const SwitchEntry& entry = entry_it->second; - if (!entry.feature_name.empty()) { - feature_switches[entry.feature_name] = entry.feature_state; - } else if (!entry.switch_name.empty()) { - command_line->AppendSwitchASCII(entry.switch_name, entry.switch_value); - flags_switches_[entry.switch_name] = entry.switch_value; - } - // If an entry doesn't match either of the above, then it is likely the - // default entry for a FEATURE_VALUE entry. Safe to ignore. - } - - if (!feature_switches.empty()) { - MergeFeatureCommandLineSwitch(feature_switches, switches::kEnableFeatures, - true, command_line); - MergeFeatureCommandLineSwitch(feature_switches, switches::kDisableFeatures, - false, command_line); - } - - if (sentinels == kAddSentinels) { - command_line->AppendSwitch(switches::kFlagSwitchesEnd); - flags_switches_[switches::kFlagSwitchesEnd] = std::string(); - } -} - -void FlagsState::MergeFeatureCommandLineSwitch( - const std::map<std::string, bool>& feature_switches, - const char* switch_name, - bool feature_state, - base::CommandLine* command_line) { - std::string original_switch_value = - command_line->GetSwitchValueASCII(switch_name); - std::vector<std::string> features = - base::FeatureList::SplitFeatureListString(original_switch_value); - // Only add features that don't already exist in the lists. - // Note: The ContainsValue() call results in O(n^2) performance, but in - // practice n should be very small. - for (const auto& entry : feature_switches) { - if (entry.second == feature_state && - !ContainsValue(features, entry.first)) { - features.push_back(entry.first); - appended_switches_[switch_name].insert(entry.first); - } - } - // Update the switch value only if it didn't change. This avoids setting an - // empty list or duplicating the same list (since AppendSwitch() adds the - // switch to the end but doesn't remove previous ones). - std::string switch_value = base::JoinString(features, ","); - if (switch_value != original_switch_value) - command_line->AppendSwitchASCII(switch_name, switch_value); -} - -} // namespace - namespace testing { const base::HistogramBase::Sample kBadSwitchFormatHistogramId = 0; -void ClearState() { - FlagsState::GetInstance()->Reset(); -} - -void SetFeatureEntries(const FeatureEntry* entries, size_t count) { - if (!entries) { - entries = kFeatureEntries; - count = arraysize(kFeatureEntries); - } - FlagsState::GetInstance()->SetFeatureEntries(entries, count); -} - const FeatureEntry* GetFeatureEntries(size_t* count) { - return FlagsState::GetInstance()->GetFeatureEntries(count); + *count = arraysize(kFeatureEntries); + return kFeatureEntries; } } // namespace testing
diff --git a/chrome/browser/about_flags.h b/chrome/browser/about_flags.h index d16274c8..71011358 100644 --- a/chrome/browser/about_flags.h +++ b/chrome/browser/about_flags.h
@@ -15,8 +15,7 @@ #include "base/metrics/histogram_base.h" #include "base/strings/string16.h" #include "components/flags_ui/feature_entry.h" - -class PrefService; +#include "components/flags_ui/flags_state.h" namespace base { class ListValue; @@ -28,15 +27,11 @@ namespace about_flags { -// A flag controlling the behavior of the |ConvertFlagsToSwitches| function - -// whether it should add the sentinel switches around flags. -enum SentinelsMode { kNoSentinels, kAddSentinels }; - // Reads the state from |flags_storage| and adds the command line flags // belonging to the active feature entries to |command_line|. void ConvertFlagsToSwitches(flags_ui::FlagsStorage* flags_storage, base::CommandLine* command_line, - SentinelsMode sentinels); + flags_ui::SentinelsMode sentinels); // Compares a set of switches of the two provided command line objects and // returns true if they are the same and false otherwise. @@ -47,17 +42,11 @@ const base::CommandLine& active_cmdline, std::set<base::CommandLine::StringType>* out_difference); -// Differentiate between generic flags available on a per session base and flags -// that influence the whole machine and can be said by the admin only. This flag -// is relevant for ChromeOS for now only and dictates whether entries marked -// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not. -enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags }; - // Gets the list of feature entries. Entries that are available for the current // platform are appended to |supported_entries|; all other entries are appended // to |unsupported_entries|. void GetFlagFeatureEntries(flags_ui::FlagsStorage* flags_storage, - FlagAccess access, + flags_ui::FlagAccess access, base::ListValue* supported_entries, base::ListValue* unsupported_entries); @@ -78,11 +67,6 @@ // Reset all flags to the default state by clearing all flags. void ResetAllFlags(flags_ui::FlagsStorage* flags_storage); -// Returns the value for the current platform. This is one of the values defined -// by the OS enum above. -// This is exposed only for testing. -int GetCurrentPlatform(); - // Sends UMA stats about experimental flag usage. This should be called once per // startup. void RecordUMAStatistics(flags_ui::FlagsStorage* flags_storage); @@ -99,14 +83,7 @@ namespace testing { -// Clears internal global state, for unit tests. -void ClearState(); - -// Sets the list of feature entries. Pass in null to use the default set. This -// does NOT take ownership of the supplied |entries|. -void SetFeatureEntries(const flags_ui::FeatureEntry* entries, size_t count); - -// Returns the current set of feature entries. +// Returns the global set of feature entries. const flags_ui::FeatureEntry* GetFeatureEntries(size_t* count); // This value is reported as switch histogram ID if switch name has unknown
diff --git a/chrome/browser/about_flags_unittest.cc b/chrome/browser/about_flags_unittest.cc index 0fbe0d9..8e0ca4b 100644 --- a/chrome/browser/about_flags_unittest.cc +++ b/chrome/browser/about_flags_unittest.cc
@@ -4,55 +4,26 @@ #include "chrome/browser/about_flags.h" -#include <stdint.h> -#include <utility> +#include <map> +#include <set> +#include <string> #include "base/feature_list.h" #include "base/files/file_path.h" #include "base/format_macros.h" #include "base/path_service.h" -#include "base/prefs/pref_registry_simple.h" -#include "base/prefs/testing_pref_service.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/grit/chromium_strings.h" -#include "components/flags_ui/flags_ui_pref_names.h" -#include "components/flags_ui/pref_service_flags_storage.h" -#include "content/public/common/content_switches.h" +#include "components/flags_ui/feature_entry.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/libxml/chromium/libxml_utils.h" -using flags_ui::FeatureEntry; - namespace about_flags { namespace { -const char kFlags1[] = "flag1"; -const char kFlags2[] = "flag2"; -const char kFlags3[] = "flag3"; -const char kFlags4[] = "flag4"; -const char kFlags5[] = "flag5"; -const char kFlags6[] = "flag6"; -const char kFlags7[] = "flag7"; - -const char kSwitch1[] = "switch"; -const char kSwitch2[] = "switch2"; -const char kSwitch3[] = "switch3"; -const char kSwitch6[] = "switch6"; -const char kValueForSwitch2[] = "value_for_switch2"; - -const char kMultiSwitch1[] = "multi_switch1"; -const char kMultiSwitch2[] = "multi_switch2"; -const char kValueForMultiSwitch2[] = "value_for_multi_switch2"; - -const char kEnableDisableValue1[] = "value1"; -const char kEnableDisableValue2[] = "value2"; - typedef base::HistogramBase::Sample Sample; typedef std::map<std::string, Sample> SwitchToIdMap; @@ -199,26 +170,26 @@ std::set<std::string> result; size_t num_entries = 0; - const FeatureEntry* entries = + const flags_ui::FeatureEntry* entries = testing::GetFeatureEntries(&num_entries); for (size_t i = 0; i < num_entries; ++i) { - const FeatureEntry& entry = entries[i]; + const flags_ui::FeatureEntry& entry = entries[i]; switch (entry.type) { - case FeatureEntry::SINGLE_VALUE: - case FeatureEntry::SINGLE_DISABLE_VALUE: + case flags_ui::FeatureEntry::SINGLE_VALUE: + case flags_ui::FeatureEntry::SINGLE_DISABLE_VALUE: result.insert(entry.command_line_switch); break; - case FeatureEntry::MULTI_VALUE: + case flags_ui::FeatureEntry::MULTI_VALUE: for (int j = 0; j < entry.num_choices; ++j) { result.insert(entry.choices[j].command_line_switch); } break; - case FeatureEntry::ENABLE_DISABLE_VALUE: + case flags_ui::FeatureEntry::ENABLE_DISABLE_VALUE: result.insert(entry.command_line_switch); result.insert(entry.disable_command_line_switch); break; - case FeatureEntry::FEATURE_VALUE: + case flags_ui::FeatureEntry::FEATURE_VALUE: break; } } @@ -227,593 +198,10 @@ } // anonymous namespace -const FeatureEntry::Choice kMultiChoices[] = { - { IDS_PRODUCT_NAME, "", "" }, - { IDS_PRODUCT_NAME, kMultiSwitch1, "" }, - { IDS_PRODUCT_NAME, kMultiSwitch2, kValueForMultiSwitch2 }, -}; - -const base::Feature kTestFeature{"FeatureName", - base::FEATURE_ENABLED_BY_DEFAULT}; - -// The entries that are set for these tests. The 3rd entry is not supported on -// the current platform, all others are. -static FeatureEntry kEntries[] = { - {kFlags1, IDS_PRODUCT_NAME, IDS_PRODUCT_NAME, - 0, // Ends up being mapped to the current platform. - FeatureEntry::SINGLE_VALUE, kSwitch1, "", nullptr, nullptr, nullptr, - nullptr, 0}, - {kFlags2, IDS_PRODUCT_NAME, IDS_PRODUCT_NAME, - 0, // Ends up being mapped to the current platform. - FeatureEntry::SINGLE_VALUE, kSwitch2, kValueForSwitch2, nullptr, nullptr, - nullptr, nullptr, 0}, - {kFlags3, IDS_PRODUCT_NAME, IDS_PRODUCT_NAME, - 0, // This ends up enabling for an OS other than the current. - FeatureEntry::SINGLE_VALUE, kSwitch3, "", nullptr, nullptr, nullptr, - nullptr, 0}, - {kFlags4, IDS_PRODUCT_NAME, IDS_PRODUCT_NAME, - 0, // Ends up being mapped to the current platform. - FeatureEntry::MULTI_VALUE, "", "", "", "", nullptr, kMultiChoices, - arraysize(kMultiChoices)}, - {kFlags5, IDS_PRODUCT_NAME, IDS_PRODUCT_NAME, - 0, // Ends up being mapped to the current platform. - FeatureEntry::ENABLE_DISABLE_VALUE, kSwitch1, kEnableDisableValue1, - kSwitch2, kEnableDisableValue2, nullptr, nullptr, 3}, - {kFlags6, IDS_PRODUCT_NAME, IDS_PRODUCT_NAME, 0, - FeatureEntry::SINGLE_DISABLE_VALUE, kSwitch6, "", nullptr, nullptr, - nullptr, nullptr, 0}, - {kFlags7, IDS_PRODUCT_NAME, IDS_PRODUCT_NAME, - 0, // Ends up being mapped to the current platform. - FeatureEntry::FEATURE_VALUE, nullptr, nullptr, nullptr, nullptr, - &kTestFeature, nullptr, 3}, -}; - -class AboutFlagsTest : public ::testing::Test { - protected: - AboutFlagsTest() : flags_storage_(&prefs_) { - prefs_.registry()->RegisterListPref( - flags_ui::prefs::kEnabledLabsExperiments); - testing::ClearState(); - } - - void SetUp() override { - for (size_t i = 0; i < arraysize(kEntries); ++i) - kEntries[i].supported_platforms = GetCurrentPlatform(); - - int os_other_than_current = 1; - while (os_other_than_current == GetCurrentPlatform()) - os_other_than_current <<= 1; - kEntries[2].supported_platforms = os_other_than_current; - - testing::SetFeatureEntries(kEntries, arraysize(kEntries)); - } - - void TearDown() override { testing::SetFeatureEntries(nullptr, 0); } - - TestingPrefServiceSimple prefs_; - flags_ui::PrefServiceFlagsStorage flags_storage_; -}; - - -TEST_F(AboutFlagsTest, NoChangeNoRestart) { - EXPECT_FALSE(IsRestartNeededToCommitChanges()); - SetFeatureEntryEnabled(&flags_storage_, kFlags1, false); - EXPECT_FALSE(IsRestartNeededToCommitChanges()); - - // kFlags6 is enabled by default, so enabling should not require a restart. - SetFeatureEntryEnabled(&flags_storage_, kFlags6, true); - EXPECT_FALSE(IsRestartNeededToCommitChanges()); -} - -TEST_F(AboutFlagsTest, ChangeNeedsRestart) { - EXPECT_FALSE(IsRestartNeededToCommitChanges()); - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - EXPECT_TRUE(IsRestartNeededToCommitChanges()); -} - -// Tests that disabling a default enabled entry requires a restart. -TEST_F(AboutFlagsTest, DisableChangeNeedsRestart) { - EXPECT_FALSE(IsRestartNeededToCommitChanges()); - SetFeatureEntryEnabled(&flags_storage_, kFlags6, false); - EXPECT_TRUE(IsRestartNeededToCommitChanges()); -} - -TEST_F(AboutFlagsTest, MultiFlagChangeNeedsRestart) { - const FeatureEntry& entry = kEntries[3]; - ASSERT_EQ(kFlags4, entry.internal_name); - EXPECT_FALSE(IsRestartNeededToCommitChanges()); - // Enable the 2nd choice of the multi-value. - SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), true); - EXPECT_TRUE(IsRestartNeededToCommitChanges()); - testing::ClearState(); - EXPECT_FALSE(IsRestartNeededToCommitChanges()); - // Enable the default choice now. - SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), true); - EXPECT_TRUE(IsRestartNeededToCommitChanges()); -} - -TEST_F(AboutFlagsTest, AddTwoFlagsRemoveOne) { - // Add two entries, check they're there. - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); - - const base::ListValue* entries_list = - prefs_.GetList(flags_ui::prefs::kEnabledLabsExperiments); - ASSERT_TRUE(entries_list != nullptr); - - ASSERT_EQ(2u, entries_list->GetSize()); - - std::string s0; - ASSERT_TRUE(entries_list->GetString(0, &s0)); - std::string s1; - ASSERT_TRUE(entries_list->GetString(1, &s1)); - - EXPECT_TRUE(s0 == kFlags1 || s1 == kFlags1); - EXPECT_TRUE(s0 == kFlags2 || s1 == kFlags2); - - // Remove one entry, check the other's still around. - SetFeatureEntryEnabled(&flags_storage_, kFlags2, false); - - entries_list = prefs_.GetList(flags_ui::prefs::kEnabledLabsExperiments); - ASSERT_TRUE(entries_list != nullptr); - ASSERT_EQ(1u, entries_list->GetSize()); - ASSERT_TRUE(entries_list->GetString(0, &s0)); - EXPECT_TRUE(s0 == kFlags1); -} - -TEST_F(AboutFlagsTest, AddTwoFlagsRemoveBoth) { - // Add two entries, check the pref exists. - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); - const base::ListValue* entries_list = - prefs_.GetList(flags_ui::prefs::kEnabledLabsExperiments); - ASSERT_TRUE(entries_list != nullptr); - - // Remove both, the pref should have been removed completely. - SetFeatureEntryEnabled(&flags_storage_, kFlags1, false); - SetFeatureEntryEnabled(&flags_storage_, kFlags2, false); - entries_list = prefs_.GetList(flags_ui::prefs::kEnabledLabsExperiments); - EXPECT_TRUE(entries_list == nullptr || entries_list->GetSize() == 0); -} - -TEST_F(AboutFlagsTest, ConvertFlagsToSwitches) { - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - command_line.AppendSwitch("foo"); - - EXPECT_TRUE(command_line.HasSwitch("foo")); - EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); - - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - - EXPECT_TRUE(command_line.HasSwitch("foo")); - EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); - EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesBegin)); - EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesEnd)); - - base::CommandLine command_line2(base::CommandLine::NO_PROGRAM); - - ConvertFlagsToSwitches(&flags_storage_, &command_line2, kNoSentinels); - - EXPECT_TRUE(command_line2.HasSwitch(kSwitch1)); - EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesBegin)); - EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd)); -} - -base::CommandLine::StringType CreateSwitch(const std::string& value) { -#if defined(OS_WIN) - return base::ASCIIToUTF16(value); -#else - return value; -#endif -} - -TEST_F(AboutFlagsTest, CompareSwitchesToCurrentCommandLine) { - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - - const std::string kDoubleDash("--"); - - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - command_line.AppendSwitch("foo"); - - base::CommandLine new_command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &new_command_line, kAddSentinels); - - EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line, - command_line, nullptr)); - { - std::set<base::CommandLine::StringType> difference; - EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine( - new_command_line, command_line, &difference)); - EXPECT_EQ(1U, difference.size()); - EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1))); - } - - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - - EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line, - command_line, nullptr)); - { - std::set<base::CommandLine::StringType> difference; - EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine( - new_command_line, command_line, &difference)); - EXPECT_TRUE(difference.empty()); - } - - // Now both have flags but different. - SetFeatureEntryEnabled(&flags_storage_, kFlags1, false); - SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); - - base::CommandLine another_command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &another_command_line, kAddSentinels); - - EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine( - new_command_line, another_command_line, nullptr)); - { - std::set<base::CommandLine::StringType> difference; - EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine( - new_command_line, another_command_line, &difference)); - EXPECT_EQ(2U, difference.size()); - EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1))); - EXPECT_EQ(1U, - difference.count(CreateSwitch(kDoubleDash + kSwitch2 + "=" + - kValueForSwitch2))); - } -} - -TEST_F(AboutFlagsTest, RemoveFlagSwitches) { - std::map<std::string, base::CommandLine::StringType> switch_list; - switch_list[kSwitch1] = base::CommandLine::StringType(); - switch_list[switches::kFlagSwitchesBegin] = base::CommandLine::StringType(); - switch_list[switches::kFlagSwitchesEnd] = base::CommandLine::StringType(); - switch_list["foo"] = base::CommandLine::StringType(); - - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - - // This shouldn't do anything before ConvertFlagsToSwitches() wasn't called. - RemoveFlagsSwitches(&switch_list); - ASSERT_EQ(4u, switch_list.size()); - EXPECT_TRUE(ContainsKey(switch_list, kSwitch1)); - EXPECT_TRUE(ContainsKey(switch_list, switches::kFlagSwitchesBegin)); - EXPECT_TRUE(ContainsKey(switch_list, switches::kFlagSwitchesEnd)); - EXPECT_TRUE(ContainsKey(switch_list, "foo")); - - // Call ConvertFlagsToSwitches(), then RemoveFlagsSwitches() again. - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - command_line.AppendSwitch("foo"); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - RemoveFlagsSwitches(&switch_list); - - // Now the about:flags-related switch should have been removed. - ASSERT_EQ(1u, switch_list.size()); - EXPECT_TRUE(ContainsKey(switch_list, "foo")); -} - -TEST_F(AboutFlagsTest, RemoveFlagSwitches_Features) { - struct { - int enabled_choice; // 0: default, 1: enabled, 2: disabled. - const char* existing_enable_features; - const char* existing_disable_features; - const char* expected_enable_features; - const char* expected_disable_features; - } cases[] = { - // Default value: Should not affect existing flags. - {0, nullptr, nullptr, nullptr, nullptr}, - {0, "A,B", "C", "A,B", "C"}, - // "Enable" option: should only affect enabled list. - {1, nullptr, nullptr, "FeatureName", nullptr}, - {1, "A,B", "C", "A,B,FeatureName", "C"}, - // "Disable" option: should only affect disabled list. - {2, nullptr, nullptr, nullptr, "FeatureName"}, - {2, "A,B", "C", "A,B", "C,FeatureName"}, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(base::StringPrintf( - "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice, - cases[i].existing_enable_features ? cases[i].existing_enable_features - : "null", - cases[i].existing_disable_features ? cases[i].existing_disable_features - : "null")); - - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - if (cases[i].existing_enable_features) { - command_line.AppendSwitchASCII(switches::kEnableFeatures, - cases[i].existing_enable_features); - } - if (cases[i].existing_disable_features) { - command_line.AppendSwitchASCII(switches::kDisableFeatures, - cases[i].existing_disable_features); - } - - testing::ClearState(); - - const std::string entry_name = base::StringPrintf( - "%s%s%d", kFlags7, flags_ui::testing::kMultiSeparator, - cases[i].enabled_choice); - SetFeatureEntryEnabled(&flags_storage_, entry_name, true); - - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - auto switch_list = command_line.GetSwitches(); - EXPECT_EQ(cases[i].expected_enable_features != nullptr, - ContainsKey(switch_list, switches::kEnableFeatures)); - if (cases[i].expected_enable_features) - EXPECT_EQ(CreateSwitch(cases[i].expected_enable_features), - switch_list[switches::kEnableFeatures]); - - EXPECT_EQ(cases[i].expected_disable_features != nullptr, - ContainsKey(switch_list, switches::kDisableFeatures)); - if (cases[i].expected_disable_features) - EXPECT_EQ(CreateSwitch(cases[i].expected_disable_features), - switch_list[switches::kDisableFeatures]); - - // RemoveFlagsSwitches() should result in the original values for these - // switches. - switch_list = command_line.GetSwitches(); - RemoveFlagsSwitches(&switch_list); - EXPECT_EQ(cases[i].existing_enable_features != nullptr, - ContainsKey(switch_list, switches::kEnableFeatures)); - if (cases[i].existing_enable_features) - EXPECT_EQ(CreateSwitch(cases[i].existing_enable_features), - switch_list[switches::kEnableFeatures]); - EXPECT_EQ(cases[i].existing_disable_features != nullptr, - ContainsKey(switch_list, switches::kEnableFeatures)); - if (cases[i].existing_disable_features) - EXPECT_EQ(CreateSwitch(cases[i].existing_disable_features), - switch_list[switches::kDisableFeatures]); - } -} - -// Tests enabling entries that aren't supported on the current platform. -TEST_F(AboutFlagsTest, PersistAndPrune) { - // Enable entries 1 and 3. - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - SetFeatureEntryEnabled(&flags_storage_, kFlags3, true); - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kSwitch3)); - - // Convert the flags to switches. Entry 3 shouldn't be among the switches - // as it is not applicable to the current platform. - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kSwitch3)); - - // FeatureEntry 3 should show still be persisted in preferences though. - const base::ListValue* entries_list = - prefs_.GetList(flags_ui::prefs::kEnabledLabsExperiments); - ASSERT_TRUE(entries_list); - EXPECT_EQ(2U, entries_list->GetSize()); - std::string s0; - ASSERT_TRUE(entries_list->GetString(0, &s0)); - EXPECT_EQ(kFlags1, s0); - std::string s1; - ASSERT_TRUE(entries_list->GetString(1, &s1)); - EXPECT_EQ(kFlags3, s1); -} - -// Tests that switches which should have values get them in the command -// line. -TEST_F(AboutFlagsTest, CheckValues) { - // Enable entries 1 and 2. - SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); - SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kSwitch2)); - - // Convert the flags to switches. - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); - EXPECT_EQ(std::string(), command_line.GetSwitchValueASCII(kSwitch1)); - EXPECT_TRUE(command_line.HasSwitch(kSwitch2)); - EXPECT_EQ(std::string(kValueForSwitch2), - command_line.GetSwitchValueASCII(kSwitch2)); - - // Confirm that there is no '=' in the command line for simple switches. - std::string switch1_with_equals = std::string("--") + - std::string(kSwitch1) + - std::string("="); -#if defined(OS_WIN) - EXPECT_EQ(base::string16::npos, - command_line.GetCommandLineString().find( - base::ASCIIToUTF16(switch1_with_equals))); -#else - EXPECT_EQ(std::string::npos, - command_line.GetCommandLineString().find(switch1_with_equals)); -#endif - - // And confirm there is a '=' for switches with values. - std::string switch2_with_equals = std::string("--") + - std::string(kSwitch2) + - std::string("="); -#if defined(OS_WIN) - EXPECT_NE(base::string16::npos, - command_line.GetCommandLineString().find( - base::ASCIIToUTF16(switch2_with_equals))); -#else - EXPECT_NE(std::string::npos, - command_line.GetCommandLineString().find(switch2_with_equals)); -#endif - - // And it should persist. - const base::ListValue* entries_list = - prefs_.GetList(flags_ui::prefs::kEnabledLabsExperiments); - ASSERT_TRUE(entries_list); - EXPECT_EQ(2U, entries_list->GetSize()); - std::string s0; - ASSERT_TRUE(entries_list->GetString(0, &s0)); - EXPECT_EQ(kFlags1, s0); - std::string s1; - ASSERT_TRUE(entries_list->GetString(1, &s1)); - EXPECT_EQ(kFlags2, s1); -} - -// Tests multi-value type entries. -TEST_F(AboutFlagsTest, MultiValues) { - const FeatureEntry& entry = kEntries[3]; - ASSERT_EQ(kFlags4, entry.internal_name); - - // Initially, the first "deactivated" option of the multi entry should - // be set. - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2)); - } - - // Enable the 2nd choice of the multi-value. - SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), true); - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); - EXPECT_TRUE(command_line.HasSwitch(kMultiSwitch2)); - EXPECT_EQ(std::string(kValueForMultiSwitch2), - command_line.GetSwitchValueASCII(kMultiSwitch2)); - } - - // Disable the multi-value entry. - SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), true); - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2)); - } -} - -// Tests that disable flags are added when an entry is disabled. -TEST_F(AboutFlagsTest, DisableFlagCommandLine) { - // Nothing selected. - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kSwitch6)); - } - - // Disable the entry 6. - SetFeatureEntryEnabled(&flags_storage_, kFlags6, false); - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_TRUE(command_line.HasSwitch(kSwitch6)); - } - - // Enable entry 6. - SetFeatureEntryEnabled(&flags_storage_, kFlags6, true); - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kSwitch6)); - } -} - -TEST_F(AboutFlagsTest, EnableDisableValues) { - const FeatureEntry& entry = kEntries[4]; - ASSERT_EQ(kFlags5, entry.internal_name); - - // Nothing selected. - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kSwitch2)); - } - - // "Enable" option selected. - SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(1), true); - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kSwitch2)); - EXPECT_EQ(kEnableDisableValue1, command_line.GetSwitchValueASCII(kSwitch1)); - } - - // "Disable" option selected. - SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), true); - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); - EXPECT_TRUE(command_line.HasSwitch(kSwitch2)); - EXPECT_EQ(kEnableDisableValue2, command_line.GetSwitchValueASCII(kSwitch2)); - } - - // "Default" option selected, same as nothing selected. - SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), true); - { - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); - EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2)); - } -} - -TEST_F(AboutFlagsTest, FeatureValues) { - const FeatureEntry& entry = kEntries[6]; - ASSERT_EQ(kFlags7, entry.internal_name); - - struct { - int enabled_choice; - const char* existing_enable_features; - const char* existing_disable_features; - const char* expected_enable_features; - const char* expected_disable_features; - } cases[] = { - // Nothing selected. - {-1, nullptr, nullptr, "", ""}, - // "Default" option selected, same as nothing selected. - {0, nullptr, nullptr, "", ""}, - // "Enable" option selected. - {1, nullptr, nullptr, "FeatureName", ""}, - // "Disable" option selected. - {2, nullptr, nullptr, "", "FeatureName"}, - // "Enable" option should get added to the existing list. - {1, "Foo,Bar", nullptr, "Foo,Bar,FeatureName", ""}, - // "Disable" option should get added to the existing list. - {2, nullptr, "Foo,Bar", "", "Foo,Bar,FeatureName"}, - }; - - for (size_t i = 0; i < arraysize(cases); ++i) { - SCOPED_TRACE(base::StringPrintf( - "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice, - cases[i].existing_enable_features ? cases[i].existing_enable_features - : "null", - cases[i].existing_disable_features ? cases[i].existing_disable_features - : "null")); - - if (cases[i].enabled_choice != -1) { - SetFeatureEntryEnabled( - &flags_storage_, entry.NameForChoice(cases[i].enabled_choice), true); - } - - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - if (cases[i].existing_enable_features) { - command_line.AppendSwitchASCII(switches::kEnableFeatures, - cases[i].existing_enable_features); - } - if (cases[i].existing_disable_features) { - command_line.AppendSwitchASCII(switches::kDisableFeatures, - cases[i].existing_disable_features); - } - - ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); - EXPECT_EQ(cases[i].expected_enable_features, - command_line.GetSwitchValueASCII(switches::kEnableFeatures)); - EXPECT_EQ(cases[i].expected_disable_features, - command_line.GetSwitchValueASCII(switches::kDisableFeatures)); - } -} - // Makes sure there are no separators in any of the entry names. -TEST_F(AboutFlagsTest, NoSeparators) { - testing::SetFeatureEntries(nullptr, 0); +TEST(AboutFlagsTest, NoSeparators) { size_t count; - const FeatureEntry* entries = testing::GetFeatureEntries(&count); + const flags_ui::FeatureEntry* entries = testing::GetFeatureEntries(&count); for (size_t i = 0; i < count; ++i) { std::string name = entries[i].internal_name; EXPECT_EQ(std::string::npos, name.find(flags_ui::testing::kMultiSeparator)) @@ -821,18 +209,6 @@ } } -TEST_F(AboutFlagsTest, GetFlagFeatureEntries) { - base::ListValue supported_entries; - base::ListValue unsupported_entries; - GetFlagFeatureEntries(&flags_storage_, kGeneralAccessFlagsOnly, - &supported_entries, &unsupported_entries); - // All |kEntries| except for |kFlags3| should be supported. - EXPECT_EQ(6u, supported_entries.GetSize()); - EXPECT_EQ(1u, unsupported_entries.GetSize()); - EXPECT_EQ(arraysize(kEntries), - supported_entries.GetSize() + unsupported_entries.GetSize()); -} - class AboutFlagsHistogramTest : public ::testing::Test { protected: // This is a helper function to check that all IDs in enum LoginCustomFlags in
diff --git a/chrome/browser/android/password_ui_view_android.cc b/chrome/browser/android/password_ui_view_android.cc index 37e7d34..2542def 100644 --- a/chrome/browser/android/password_ui_view_android.cc +++ b/chrome/browser/android/password_ui_view_android.cc
@@ -12,11 +12,11 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/pref_names.h" -#include "chrome/common/url_constants.h" #include "components/autofill/core/common/password_form.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/password_manager/core/browser/affiliation_utils.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "components/password_manager/core/browser/password_manager_constants.h" #include "components/password_manager/core/common/experiments.h" #include "components/password_manager/core/common/password_manager_switches.h" #include "jni/PasswordUIView_jni.h" @@ -114,8 +114,8 @@ ScopedJavaLocalRef<jstring> GetAccountDashboardURL( JNIEnv* env, const JavaParamRef<jclass>&) { - return ConvertUTF8ToJavaString(env, - chrome::kPasswordManagerAccountDashboardURL); + return ConvertUTF8ToJavaString( + env, password_manager::kPasswordManagerAccountDashboardURL); } static jboolean ShouldUseSmartLockBranding(JNIEnv* env,
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index ab262c6..2b6e9cc4 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc
@@ -287,20 +287,6 @@ } } -bool TabAndroid::HasOfflinePages() const { - if (!offline_pages::IsOfflinePagesEnabled()) - return false; - offline_pages::OfflinePageModel* offline_page_model = - offline_pages::OfflinePageModelFactory::GetForBrowserContext( - GetProfile()); - return !offline_page_model->GetAllPages().empty(); -} - -void TabAndroid::ShowOfflinePages() { - JNIEnv* env = base::android::AttachCurrentThread(); - Java_Tab_showOfflinePages(env, weak_java_tab_.get(env).obj()); -} - void TabAndroid::SwapTabContents(content::WebContents* old_contents, content::WebContents* new_contents, bool did_start_load, @@ -774,6 +760,10 @@ jlong TabAndroid::GetBookmarkId(JNIEnv* env, jobject obj, jboolean only_editable) { + return GetBookmarkIdHelper(only_editable); +} + +int64_t TabAndroid::GetBookmarkIdHelper(bool only_editable) const { GURL url = dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl( web_contents()->GetURL()); Profile* profile = GetProfile(); @@ -802,9 +792,51 @@ return -1; } +bool TabAndroid::HasOfflinePages() const { + if (!offline_pages::IsOfflinePagesEnabled()) + return false; + offline_pages::OfflinePageModel* offline_page_model = + offline_pages::OfflinePageModelFactory::GetForBrowserContext( + GetProfile()); + return !offline_page_model->GetAllPages().empty(); +} + +void TabAndroid::ShowOfflinePages() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_Tab_showOfflinePages(env, weak_java_tab_.get(env).obj()); +} + +void TabAndroid::LoadOfflineCopy(const GURL& url) { + if (!offline_pages::IsOfflinePagesEnabled()) + return; + + // Offline copy is only saved for a bookmarked page. + int64_t bookmark_id = GetBookmarkIdHelper(true); + if (bookmark_id == -1) + return; + + offline_pages::OfflinePageModel* offline_page_model = + offline_pages::OfflinePageModelFactory::GetForBrowserContext( + GetProfile()); + if (!offline_page_model) + return; + + const offline_pages::OfflinePageItem* offline_page = + offline_page_model->GetPageByBookmarkId(bookmark_id); + if (!offline_page || offline_page->url != url) + return; + + GURL offline_url = offline_page->GetOfflineURL(); + if (!offline_url.is_valid()) + return; + + content::NavigationController::LoadURLParams load_params(offline_url); + web_contents()->GetController().LoadURLWithParams(load_params); +} + jboolean TabAndroid::HasOfflineCopy(JNIEnv* env, jobject obj) { // Offline copy is only saved for a bookmarked page. - jlong bookmark_id = GetBookmarkId(env, obj, true); + int64_t bookmark_id = GetBookmarkIdHelper(true); if (bookmark_id == -1) return false;
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h index c54c647..ae5f022 100644 --- a/chrome/browser/android/tab_android.h +++ b/chrome/browser/android/tab_android.h
@@ -128,6 +128,7 @@ bool HasOfflinePages() const; void ShowOfflinePages(); + void LoadOfflineCopy(const GURL& url); // Overridden from CoreTabHelperDelegate: void SwapTabContents(content::WebContents* old_contents, @@ -242,6 +243,8 @@ private: prerender::PrerenderManager* GetPrerenderManager() const; + int64_t GetBookmarkIdHelper(bool only_editable) const; + const offline_pages::OfflinePageItem* GetOfflinePage(const GURL& url) const; JavaObjectWeakGlobalRef weak_java_tab_;
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 5114e39..7efa965 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -914,7 +914,7 @@ g_browser_process->local_state()); about_flags::ConvertFlagsToSwitches(&flags_storage_, base::CommandLine::ForCurrentProcess(), - about_flags::kAddSentinels); + flags_ui::kAddSentinels); } #endif // !defined(OS_CHROMEOS) @@ -1353,7 +1353,7 @@ // Setup.exe has determined that we need to run a retention experiment // and has lauched chrome to show the experiment UI. It is guaranteed that // no other Chrome is currently running as the process singleton was - // sucessfully grabbed above. + // successfully grabbed above. int try_chrome_int; base::StringToInt(try_chrome, &try_chrome_int); TryChromeDialogView::Result answer = TryChromeDialogView::Show(
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 2956d6e5..6ad60683 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1963,8 +1963,7 @@ } void ChromeContentBrowserClient::AllowCertificateError( - int render_process_id, - int render_frame_id, + content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, @@ -1974,6 +1973,7 @@ bool expired_previous_decision, const base::Callback<void(bool)>& callback, content::CertificateRequestResultType* result) { + DCHECK(web_contents); if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME) { // A sub-resource has a certificate error. The user doesn't really // have a context for making the right decision, so block the @@ -1984,16 +1984,8 @@ } // If the tab is being prerendered, cancel the prerender and the request. - content::RenderFrameHost* render_frame_host = - content::RenderFrameHost::FromID(render_process_id, render_frame_id); - WebContents* tab = WebContents::FromRenderFrameHost(render_frame_host); - if (!tab) { - NOTREACHED(); - return; - } - prerender::PrerenderContents* prerender_contents = - prerender::PrerenderContents::FromWebContents(tab); + prerender::PrerenderContents::FromWebContents(web_contents); if (prerender_contents) { prerender_contents->Destroy(prerender::FINAL_STATUS_SSL_ERROR); *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL; @@ -2016,8 +2008,9 @@ new SafeBrowsingSSLCertReporter(safe_browsing_service ? safe_browsing_service->ui_manager() : nullptr)); - SSLErrorHandler::HandleSSLError(tab, cert_error, ssl_info, request_url, - options_mask, cert_reporter.Pass(), callback); + SSLErrorHandler::HandleSSLError(web_contents, cert_error, ssl_info, + request_url, options_mask, + cert_reporter.Pass(), callback); } void ChromeContentBrowserClient::SelectClientCertificate(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 0295436..ce1a1ad0 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -178,8 +178,7 @@ scoped_ptr<storage::QuotaEvictionPolicy> GetTemporaryStorageEvictionPolicy( content::BrowserContext* context) override; void AllowCertificateError( - int render_process_id, - int render_frame_id, + content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url,
diff --git a/chrome/browser/chrome_elf_init_win.cc b/chrome/browser/chrome_elf_init_win.cc index 28af7f8..eb5cf5b 100644 --- a/chrome/browser/chrome_elf_init_win.cc +++ b/chrome/browser/chrome_elf_init_win.cc
@@ -99,7 +99,7 @@ // Report all successful blacklist interceptions. ReportSuccessfulBlocks(); - // Schedule another task to report all sucessful interceptions later. + // Schedule another task to report all successful interceptions later. // This time delay should be long enough to catch any dlls that attempt to // inject after Chrome has started up. content::BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc b/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc index 676e356..917cbcb 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc +++ b/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/thread_task_runner_handle.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/file_manager/fileapi_util.h" #include "chrome/browser/chromeos/fileapi/external_file_url_util.h" @@ -19,7 +20,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/url_constants.h" -#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_info.h" @@ -163,6 +163,7 @@ net::NetworkDelegate* network_delegate) : net::URLRequestJob(request, network_delegate), profile_id_(profile_id), + range_parse_result_(net::OK), remaining_bytes_(0), weak_ptr_factory_(this) {} @@ -170,24 +171,40 @@ const net::HttpRequestHeaders& headers) { std::string range_header; if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { - // Note: We only support single range requests. + // Currently this job only cares about the Range header, and only supports + // single range requests. Note that validation is deferred to Start, + // because NotifyStartError is not legal to call since the job has not + // started. std::vector<net::HttpByteRange> ranges; if (net::HttpUtil::ParseRangeHeader(range_header, &ranges) && ranges.size() == 1) { byte_range_ = ranges[0]; } else { - // Failed to parse Range: header, so notify the error. - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; } } } void ExternalFileURLRequestJob::Start() { + // Post a task to invoke StartAsync asynchronously to avoid re-entering the + // delegate, because NotifyStartError is not legal to call synchronously in + // Start(). + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ExternalFileURLRequestJob::StartAsync, + weak_ptr_factory_.GetWeakPtr())); +} + +void ExternalFileURLRequestJob::StartAsync() { DVLOG(1) << "Starting request"; DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!stream_reader_); + if (range_parse_result_ != net::OK) { + NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, + range_parse_result_)); + return; + } + // We only support GET request. if (request()->method() != "GET") { LOG(WARNING) << "Failed to start request: " << request()->method() @@ -327,37 +344,23 @@ return true; } -bool ExternalFileURLRequestJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int ExternalFileURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(stream_reader_); - if (remaining_bytes_ == 0) { - *bytes_read = 0; - return true; - } + if (remaining_bytes_ == 0) + return 0; const int result = stream_reader_->Read( buf, std::min<int64>(buf_size, remaining_bytes_), base::Bind(&ExternalFileURLRequestJob::OnReadCompleted, weak_ptr_factory_.GetWeakPtr())); - if (result == net::ERR_IO_PENDING) { - // The data is not yet available. - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; - } - if (result < 0) { - // An error occurs. - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); - return false; - } + if (result < 0) + return result; - // Reading has been finished immediately. - *bytes_read = result; remaining_bytes_ -= result; - return true; + return result; } ExternalFileURLRequestJob::~ExternalFileURLRequestJob() { @@ -366,15 +369,10 @@ void ExternalFileURLRequestJob::OnReadCompleted(int read_result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (read_result < 0) { - DCHECK_NE(read_result, net::ERR_IO_PENDING); - NotifyDone( - net::URLRequestStatus(net::URLRequestStatus::FAILED, read_result)); - } + if (read_result > 0) + remaining_bytes_ -= read_result; - remaining_bytes_ -= read_result; - SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status. - NotifyReadComplete(read_result); + ReadRawDataComplete(read_result); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_request_job.h b/chrome/browser/chromeos/fileapi/external_file_url_request_job.h index a026e43..dff3379b 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_request_job.h +++ b/chrome/browser/chromeos/fileapi/external_file_url_request_job.h
@@ -63,12 +63,17 @@ void Kill() override; bool GetMimeType(std::string* mime_type) const override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; protected: ~ExternalFileURLRequestJob() override; private: + // Helper method to start the job. Should be called asynchronously because + // NotifyStartError() is not legal to call synchronously in + // URLRequestJob::Start(). + void StartAsync(); + // Called from an internal helper class defined in drive_url_request_job.cc, // which is running on the UI thread. void OnHelperResultObtained( @@ -91,6 +96,7 @@ void* const profile_id_; // The range of the file to be returned. + net::Error range_parse_result_; net::HttpByteRange byte_range_; int64 remaining_bytes_;
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.cc b/chrome/browser/chromeos/login/app_launch_signin_screen.cc index 61fa439..053ff66d 100644 --- a/chrome/browser/chromeos/login/app_launch_signin_screen.cc +++ b/chrome/browser/chromeos/login/app_launch_signin_screen.cc
@@ -106,7 +106,7 @@ void AppLaunchSigninScreen::OnSigninScreenReady() { } -void AppLaunchSigninScreen::RemoveUser(const std::string& username) { +void AppLaunchSigninScreen::RemoveUser(const AccountId& account_id) { NOTREACHED(); }
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.h b/chrome/browser/chromeos/login/app_launch_signin_screen.h index 14dfec1..c875b30 100644 --- a/chrome/browser/chromeos/login/app_launch_signin_screen.h +++ b/chrome/browser/chromeos/login/app_launch_signin_screen.h
@@ -62,7 +62,7 @@ void LoadWallpaper(const std::string& username) override; void LoadSigninWallpaper() override; void OnSigninScreenReady() override; - void RemoveUser(const std::string& username) override; + void RemoveUser(const AccountId& account_id) override; void ResyncUserData() override; void ShowEnterpriseEnrollmentScreen() override; void ShowEnableDebuggingScreen() override;
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index f018373..83b988b 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -189,10 +189,10 @@ // content/browser/renderer_host/render_process_host_impl.cc. cc::switches::kDisableCachedPictureRaster, cc::switches::kDisableCompositedAntialiasing, - cc::switches::kDisableCompositorPropertyTrees, cc::switches::kDisableMainFrameBeforeActivation, cc::switches::kDisableThreadedAnimation, cc::switches::kEnableBeginFrameScheduling, + cc::switches::kEnableCompositorPropertyTrees, cc::switches::kEnableGpuBenchmarking, cc::switches::kEnablePropertyTreeVerification, cc::switches::kEnableMainFrameBeforeActivation,
diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h index eedec2f3..070901b 100644 --- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h +++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h
@@ -88,7 +88,7 @@ // auth code to authentication token, then tries to enroll the device with the // received token. // If |fetch_additional_token| is true, the helper fetches an additional token - // and passes it to the |status_consumer| on successfull enrollment. + // and passes it to the |status_consumer| on successful enrollment. // EnrollUsingAuthCode can be called only once during this object's lifetime, // and only if neither of EnrollUsing* methods was called before. virtual void EnrollUsingAuthCode(const std::string& auth_code,
diff --git a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc index 196b81b..4d00564 100644 --- a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc
@@ -77,7 +77,9 @@ void ChromeUserSelectionScreen::CheckForPublicSessionDisplayNameChange( policy::DeviceLocalAccountPolicyBroker* broker) { - const AccountId& account_id = GetAccountIdOfKnownUser(broker->user_id()); + const AccountId& account_id = + user_manager::UserManager::GetKnownUserAccountId(broker->user_id(), + std::string()); DCHECK(account_id.is_valid()); const std::string& display_name = broker->GetDisplayName(); if (display_name == public_session_display_names_[account_id]) @@ -107,7 +109,9 @@ void ChromeUserSelectionScreen::CheckForPublicSessionLocalePolicyChange( policy::DeviceLocalAccountPolicyBroker* broker) { - const AccountId& account_id = GetAccountIdOfKnownUser(broker->user_id()); + const AccountId& account_id = + user_manager::UserManager::GetKnownUserAccountId(broker->user_id(), + std::string()); DCHECK(account_id.is_valid()); const policy::PolicyMap::Entry* entry = broker->core()->store()->policy_map().Get(policy::key::kSessionLocales);
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc index 645f1002..c2df683 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -246,26 +246,6 @@ (token_status == user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN); } -// static -AccountId UserSelectionScreen::GetAccountIdOfKnownUser( - const std::string& user_id) { - if (user_id.empty()) - return EmptyAccountId(); - - const AccountId initial_account_id = AccountId::FromUserEmail(user_id); - - user_manager::UserManager* user_manager = user_manager::UserManager::Get(); - if (!user_manager) - return initial_account_id; - - AccountId known_account_id(EmptyAccountId()); - if (user_manager->GetKnownUserAccountId(initial_account_id, - &known_account_id)) - return known_account_id; - - return initial_account_id; -} - void UserSelectionScreen::SetHandler(LoginDisplayWebUIHandler* handler) { handler_ = handler; } @@ -284,20 +264,20 @@ activity_detector->AddObserver(this); } -void UserSelectionScreen::OnBeforeUserRemoved(const std::string& username) { +void UserSelectionScreen::OnBeforeUserRemoved(const AccountId& account_id) { for (user_manager::UserList::iterator it = users_.begin(); it != users_.end(); ++it) { - if ((*it)->email() == username) { + if ((*it)->GetAccountId() == account_id) { users_.erase(it); break; } } } -void UserSelectionScreen::OnUserRemoved(const std::string& username) { +void UserSelectionScreen::OnUserRemoved(const AccountId& account_id) { if (!handler_) return; - handler_->OnUserRemoved(username, users_.empty()); + handler_->OnUserRemoved(account_id, users_.empty()); } void UserSelectionScreen::OnUserImageChanged(const user_manager::User& user) { @@ -369,7 +349,8 @@ std::string owner_email; chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner_email); - const AccountId owner(GetAccountIdOfKnownUser(owner_email)); + const AccountId owner = user_manager::UserManager::GetKnownUserAccountId( + owner_email, std::string()); policy::BrowserPolicyConnectorChromeOS* connector = g_browser_process->platform_part()->browser_policy_connector_chromeos(); @@ -457,7 +438,8 @@ void UserSelectionScreen::SetAuthType(const std::string& user_id, AuthType auth_type, const base::string16& initial_value) { - const AccountId& account_id = GetAccountIdOfKnownUser(user_id); + const AccountId& account_id = + user_manager::UserManager::GetKnownUserAccountId(user_id, std::string()); if (GetAuthType(account_id.GetUserEmail()) == FORCE_OFFLINE_PASSWORD) return; DCHECK(GetAuthType(account_id.GetUserEmail()) != FORCE_OFFLINE_PASSWORD || @@ -468,7 +450,8 @@ proximity_auth::ScreenlockBridge::LockHandler::AuthType UserSelectionScreen::GetAuthType(const std::string& username) const { - const AccountId& account_id = GetAccountIdOfKnownUser(username); + const AccountId& account_id = + user_manager::UserManager::GetKnownUserAccountId(username, std::string()); if (user_auth_type_map_.find(account_id) == user_auth_type_map_.end()) return OFFLINE_PASSWORD; return user_auth_type_map_.find(account_id)->second; @@ -496,12 +479,14 @@ scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue(); if (!icon || icon->empty()) return; - const AccountId account_id = GetAccountIdOfKnownUser(user_id); + const AccountId account_id = + user_manager::UserManager::GetKnownUserAccountId(user_id, std::string()); view_->ShowUserPodCustomIcon(account_id, *icon); } void UserSelectionScreen::HideUserPodCustomIcon(const std::string& user_id) { - const AccountId account_id = GetAccountIdOfKnownUser(user_id); + const AccountId account_id = + user_manager::UserManager::GetKnownUserAccountId(user_id, std::string()); view_->HideUserPodCustomIcon(account_id); } @@ -523,7 +508,8 @@ const std::string& key_label) { DCHECK_EQ(GetScreenType(), SIGNIN_SCREEN); - UserContext user_context(GetAccountIdOfKnownUser(user_id)); + UserContext user_context( + user_manager::UserManager::GetKnownUserAccountId(user_id, std::string())); user_context.SetAuthFlow(UserContext::AUTH_FLOW_EASY_UNLOCK); user_context.SetKey(Key(secret)); user_context.GetKey()->SetLabel(key_label);
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.h b/chrome/browser/chromeos/login/screens/user_selection_screen.h index 71dcb990..70faa8be 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.h +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.h
@@ -48,8 +48,8 @@ virtual void Init(const user_manager::UserList& users, bool show_guest); void OnUserImageChanged(const user_manager::User& user); - void OnBeforeUserRemoved(const std::string& username); - void OnUserRemoved(const std::string& username); + void OnBeforeUserRemoved(const AccountId& account_id); + void OnUserRemoved(const AccountId& account_id); void OnPasswordClearTimerExpired(); @@ -109,10 +109,6 @@ static bool ShouldForceOnlineSignIn(const user_manager::User* user); protected: - // This call forms full account id of a known user by email. - // This is a temporary call while migrating to AccountId. - static AccountId GetAccountIdOfKnownUser(const std::string& user_id); - LoginDisplayWebUIHandler* handler_; LoginDisplay::Delegate* login_display_delegate_; UserBoardView* view_;
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index f06ccea..5958dc6 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -242,7 +242,7 @@ base::CommandLine user_flags(base::CommandLine::NO_PROGRAM); flags_ui::PrefServiceFlagsStorage flags_storage_(profile->GetPrefs()); about_flags::ConvertFlagsToSwitches(&flags_storage_, &user_flags, - about_flags::kAddSentinels); + flags_ui::kAddSentinels); return user_flags; }
diff --git a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc index ad33d48..1a1efdb 100644 --- a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc +++ b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
@@ -129,9 +129,9 @@ private: // user_manager::RemoveUserDelegate: - void OnBeforeUserRemoved(const std::string& username) override {} + void OnBeforeUserRemoved(const AccountId& account_id) override {} - void OnUserRemoved(const std::string& username) override { + void OnUserRemoved(const AccountId& account_id) override { user_removal_loop_.Quit(); }
diff --git a/chrome/browser/chromeos/login/signin_screen_controller.cc b/chrome/browser/chromeos/login/signin_screen_controller.cc index eb098526..dc612d70 100644 --- a/chrome/browser/chromeos/login/signin_screen_controller.cc +++ b/chrome/browser/chromeos/login/signin_screen_controller.cc
@@ -58,17 +58,16 @@ } } -void SignInScreenController::RemoveUser(const std::string& user_id) { - user_manager::UserManager::Get()->RemoveUser( - AccountId::FromUserEmail(user_id), this); +void SignInScreenController::RemoveUser(const AccountId& account_id) { + user_manager::UserManager::Get()->RemoveUser(account_id, this); } -void SignInScreenController::OnBeforeUserRemoved(const std::string& username) { - user_selection_screen_->OnBeforeUserRemoved(username); +void SignInScreenController::OnBeforeUserRemoved(const AccountId& account_id) { + user_selection_screen_->OnBeforeUserRemoved(account_id); } -void SignInScreenController::OnUserRemoved(const std::string& username) { - user_selection_screen_->OnUserRemoved(username); +void SignInScreenController::OnUserRemoved(const AccountId& account_id) { + user_selection_screen_->OnUserRemoved(account_id); } void SignInScreenController::SendUserList() {
diff --git a/chrome/browser/chromeos/login/signin_screen_controller.h b/chrome/browser/chromeos/login/signin_screen_controller.h index e341062..fb9b9817 100644 --- a/chrome/browser/chromeos/login/signin_screen_controller.h +++ b/chrome/browser/chromeos/login/signin_screen_controller.h
@@ -14,6 +14,8 @@ #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +class AccountId; + namespace chromeos { class LoginDisplayWebUIHandler; @@ -47,18 +49,18 @@ // Query to remove user with specified id. // TODO(antrim): move to user selection screen handler. - void RemoveUser(const std::string& user_id); + void RemoveUser(const AccountId& account_id); + private: // user_manager::RemoveUserDelegate implementation: - void OnBeforeUserRemoved(const std::string& username) override; - void OnUserRemoved(const std::string& username) override; + void OnBeforeUserRemoved(const AccountId& account_id) override; + void OnUserRemoved(const AccountId& account_id) override; // content::NotificationObserver implementation. void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; - private: static SignInScreenController* instance_; OobeDisplay* oobe_display_;
diff --git a/chrome/browser/chromeos/login/ui/mock_login_display.h b/chrome/browser/chromeos/login/ui/mock_login_display.h index 4af0487..ae65703 100644 --- a/chrome/browser/chromeos/login/ui/mock_login_display.h +++ b/chrome/browser/chromeos/login/ui/mock_login_display.h
@@ -9,6 +9,8 @@ #include "chrome/browser/chromeos/login/ui/login_display.h" #include "testing/gmock/include/gmock/gmock.h" +class AccountId; + namespace chromeos { class MockLoginDisplay : public LoginDisplay { @@ -26,8 +28,8 @@ 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&)); - MOCK_METHOD1(OnUserRemoved, void(const std::string&)); + MOCK_METHOD1(OnBeforeUserRemoved, void(const AccountId&)); + MOCK_METHOD1(OnUserRemoved, void(const AccountId&)); private: DISALLOW_COPY_AND_ASSIGN(MockLoginDisplay);
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.cc b/chrome/browser/chromeos/login/ui/webui_login_display.cc index 522ca4e..36ca55a 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_display.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_display.cc
@@ -248,8 +248,8 @@ delegate_->OnSigninScreenReady(); } -void WebUILoginDisplay::RemoveUser(const std::string& user_id) { - SignInScreenController::Get()->RemoveUser(user_id); +void WebUILoginDisplay::RemoveUser(const AccountId& account_id) { + SignInScreenController::Get()->RemoveUser(account_id); } void WebUILoginDisplay::ResyncUserData() {
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.h b/chrome/browser/chromeos/login/ui/webui_login_display.h index 408bf28..3dc8c90 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_display.h +++ b/chrome/browser/chromeos/login/ui/webui_login_display.h
@@ -17,6 +17,8 @@ #include "ui/base/user_activity/user_activity_observer.h" #include "ui/views/widget/widget.h" +class AccountId; + namespace chromeos { // WebUI-based login UI implementation. @@ -35,7 +37,7 @@ bool show_users, bool show_new_user) override; void OnPreferencesChanged() override; - void RemoveUser(const std::string& user_id) override; + void RemoveUser(const AccountId& account_id) override; void SetUIEnabled(bool is_enabled) override; void ShowError(int error_msg_id, int login_attempts,
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc index 40e4a0ee..fd4df22 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -506,7 +506,7 @@ } void ChromeUserManagerImpl::OnUserRemoved(const AccountId& account_id) { - RemoveReportingUser(FullyCanonicalize(account_id.GetUserEmail())); + RemoveReportingUser(account_id); } const std::string& ChromeUserManagerImpl::GetApplicationLocale() const { @@ -1150,23 +1150,24 @@ void ChromeUserManagerImpl::SetUserAffiliation( const std::string& user_email, const AffiliationIDSet& user_affiliation_ids) { - std::string canonicalized_email = FullyCanonicalize(user_email); - user_manager::User* user = - FindUserAndModify(AccountId::FromUserEmail(canonicalized_email)); + const AccountId& account_id = + user_manager::UserManager::GetKnownUserAccountId(user_email, + std::string()); + user_manager::User* user = FindUserAndModify(account_id); if (user) { policy::BrowserPolicyConnectorChromeOS const* const connector = g_browser_process->platform_part()->browser_policy_connector_chromeos(); const bool is_affiliated = chromeos::IsUserAffiliated( user_affiliation_ids, connector->GetDeviceAffiliationIDs(), - canonicalized_email, connector->GetEnterpriseDomain()); + account_id.GetUserEmail(), connector->GetEnterpriseDomain()); user->set_affiliation(is_affiliated); if (user->GetType() == user_manager::USER_TYPE_REGULAR) { if (is_affiliated) { - AddReportingUser(canonicalized_email); + AddReportingUser(account_id); } else { - RemoveReportingUser(canonicalized_email); + RemoveReportingUser(account_id); } } } @@ -1179,15 +1180,16 @@ return !(reporting_users.Find(user_id_value) == reporting_users.end()); } -void ChromeUserManagerImpl::AddReportingUser(const std::string& user_id) { +void ChromeUserManagerImpl::AddReportingUser(const AccountId& account_id) { ListPrefUpdate users_update(GetLocalState(), kReportingUsers); users_update->AppendIfNotPresent( - new base::StringValue(FullyCanonicalize(user_id))); + new base::StringValue(account_id.GetUserEmail())); } -void ChromeUserManagerImpl::RemoveReportingUser(const std::string& user_id) { +void ChromeUserManagerImpl::RemoveReportingUser(const AccountId& account_id) { ListPrefUpdate users_update(GetLocalState(), kReportingUsers); - users_update->Remove(base::StringValue(FullyCanonicalize(user_id)), NULL); + users_update->Remove( + base::StringValue(FullyCanonicalize(account_id.GetUserEmail())), NULL); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h index 20cbdba..206fd43 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h +++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.h
@@ -216,10 +216,10 @@ void UpdateUserTimeZoneRefresher(Profile* profile); // Adds user to the list of the users who should be reported. - void AddReportingUser(const std::string& user_id); + void AddReportingUser(const AccountId& account_id); // Removes user from the list of the users who should be reported. - void RemoveReportingUser(const std::string& user_id); + void RemoveReportingUser(const AccountId& account_id); // Interface to the signed settings store. CrosSettings* cros_settings_;
diff --git a/chrome/browser/chromeos/settings/owner_flags_storage.cc b/chrome/browser/chromeos/settings/owner_flags_storage.cc index a2312648..b0d097d 100644 --- a/chrome/browser/chromeos/settings/owner_flags_storage.cc +++ b/chrome/browser/chromeos/settings/owner_flags_storage.cc
@@ -20,7 +20,7 @@ OwnerFlagsStorage::OwnerFlagsStorage( PrefService* prefs, ownership::OwnerSettingsService* owner_settings_service) - : ::flags_ui::PrefServiceFlagsStorage(prefs), + : flags_ui::PrefServiceFlagsStorage(prefs), owner_settings_service_(owner_settings_service) { // Make this code more unit test friendly. if (g_browser_process->local_state()) { @@ -57,7 +57,7 @@ base::CommandLine command_line(base::CommandLine::NO_PROGRAM); ::about_flags::ConvertFlagsToSwitches(this, &command_line, - ::about_flags::kNoSentinels); + flags_ui::kNoSentinels); base::CommandLine::StringVector switches = command_line.argv(); for (base::CommandLine::StringVector::const_iterator it = switches.begin() + 1;
diff --git a/chrome/browser/component_updater/ev_whitelist_component_installer.cc b/chrome/browser/component_updater/ev_whitelist_component_installer.cc index 086feaa..aba62c5 100644 --- a/chrome/browser/component_updater/ev_whitelist_component_installer.cc +++ b/chrome/browser/component_updater/ev_whitelist_component_installer.cc
@@ -52,7 +52,7 @@ return; } - VLOG(0) << "EV whitelist: Sucessfully loaded."; + VLOG(0) << "EV whitelist: Successfully loaded."; packed_ct_ev_whitelist::SetEVCertsWhitelist(new_whitelist); }
diff --git a/chrome/browser/devtools/devtools_network_transaction.cc b/chrome/browser/devtools/devtools_network_transaction.cc index c54d87e..5f815aa 100644 --- a/chrome/browser/devtools/devtools_network_transaction.cc +++ b/chrome/browser/devtools/devtools_network_transaction.cc
@@ -150,8 +150,10 @@ return net::ERR_INTERNET_DISCONNECTED; } - if (interceptor_) - interceptor_->AddThrottable(this); + if (!interceptor_) + return network_transaction_->Start(request_, callback, net_log); + + interceptor_->AddThrottable(this); int rv = network_transaction_->Start(request_, proxy_callback_, net_log); return SetupCallback(callback, rv, START); } @@ -175,6 +177,8 @@ const net::CompletionCallback& callback) { if (failed_) return net::ERR_INTERNET_DISCONNECTED; + if (!interceptor_) + return network_transaction_->RestartIgnoringLastError(callback); int rv = network_transaction_->RestartIgnoringLastError(proxy_callback_); return SetupCallback(callback, rv, RESTART_IGNORING_LAST_ERROR); } @@ -185,6 +189,10 @@ const net::CompletionCallback& callback) { if (failed_) return net::ERR_INTERNET_DISCONNECTED; + if (!interceptor_) { + return network_transaction_->RestartWithCertificate( + client_cert, client_private_key, callback); + } int rv = network_transaction_->RestartWithCertificate( client_cert, client_private_key, proxy_callback_); return SetupCallback(callback, rv, RESTART_WITH_CERTIFICATE); @@ -195,6 +203,8 @@ const net::CompletionCallback& callback) { if (failed_) return net::ERR_INTERNET_DISCONNECTED; + if (!interceptor_) + return network_transaction_->RestartWithAuth(credentials, callback); int rv = network_transaction_->RestartWithAuth(credentials, proxy_callback_); return SetupCallback(callback, rv, RESTART_WITH_AUTH); } @@ -209,6 +219,8 @@ const net::CompletionCallback& callback) { if (failed_) return net::ERR_INTERNET_DISCONNECTED; + if (!interceptor_) + return network_transaction_->Read(buf, buf_len, callback); int rv = network_transaction_->Read(buf, buf_len, proxy_callback_); return SetupCallback(callback, rv, READ); } @@ -284,6 +296,8 @@ int DevToolsNetworkTransaction::ResumeNetworkStart() { if (failed_) return net::ERR_INTERNET_DISCONNECTED; + if (!interceptor_) + return network_transaction_->ResumeNetworkStart(); return network_transaction_->ResumeNetworkStart(); }
diff --git a/chrome/browser/download/notification/download_notification_browsertest.cc b/chrome/browser/download/notification/download_notification_browsertest.cc index 8123406..51b7f38 100644 --- a/chrome/browser/download/notification/download_notification_browsertest.cc +++ b/chrome/browser/download/notification/download_notification_browsertest.cc
@@ -385,7 +385,13 @@ std::string notification_id_; }; -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadFile) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadFile DISABLED_DownloadFile +#else +#define MAYBE_DownloadFile DownloadFile +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_DownloadFile) { CreateDownload(); EXPECT_EQ(l10n_util::GetStringFUTF16( @@ -437,7 +443,13 @@ EXPECT_FALSE(GetNotification(notification_id())); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadDangerousFile) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadDangerousFile DISABLED_DownloadDangerousFile +#else +#define MAYBE_DownloadDangerousFile DownloadDangerousFile +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_DownloadDangerousFile) { GURL download_url(embedded_test_server()->GetURL( "/downloads/dangerous/dangerous.swf")); @@ -488,7 +500,13 @@ EXPECT_TRUE(base::PathExists(GetDownloadPath().Append(filename.BaseName()))); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DiscardDangerousFile) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DiscardDangerousFile DISABLED_DiscardDangerousFile +#else +#define MAYBE_DiscardDangerousFile DiscardDangerousFile +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_DiscardDangerousFile) { GURL download_url(embedded_test_server()->GetURL( "/downloads/dangerous/dangerous.swf")); @@ -537,7 +555,13 @@ EXPECT_FALSE(base::PathExists(GetDownloadPath().Append(filename.BaseName()))); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadImageFile) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadImageFile DISABLED_DownloadImageFile +#else +#define MAYBE_DownloadImageFile DownloadImageFile +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_DownloadImageFile) { GURL download_url(embedded_test_server()->GetURL( "/downloads/image-octet-stream.png")); @@ -559,8 +583,14 @@ } } +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_CloseNotificationAfterDownload DISABLED_CloseNotificationAfterDownload +#else +#define MAYBE_CloseNotificationAfterDownload CloseNotificationAfterDownload +#endif IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, - CloseNotificationAfterDownload) { + MAYBE_CloseNotificationAfterDownload) { CreateDownload(); // Requests to complete the download. @@ -592,8 +622,14 @@ EXPECT_EQ(content::DownloadItem::COMPLETE, downloads[0]->GetState()); } +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_CloseNotificationWhileDownloading DISABLED_CloseNotificationWhileDownloading +#else +#define MAYBE_CloseNotificationWhileDownloading CloseNotificationWhileDownloading +#endif IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, - CloseNotificationWhileDownloading) { + MAYBE_CloseNotificationWhileDownloading) { CreateDownload(); // Closes the notification. @@ -632,7 +668,13 @@ EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id())); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, InterruptDownload) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_InterruptDownload DISABLED_InterruptDownload +#else +#define MAYBE_InterruptDownload InterruptDownload +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_InterruptDownload) { CreateDownload(); // Installs observers before requesting. @@ -672,8 +714,14 @@ GetNotification(notification_id())->type()); } +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_InterruptDownloadAfterClosingNotification DISABLED_InterruptDownloadAfterClosingNotification +#else +#define MAYBE_InterruptDownloadAfterClosingNotification InterruptDownloadAfterClosingNotification +#endif IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, - InterruptDownloadAfterClosingNotification) { + MAYBE_InterruptDownloadAfterClosingNotification) { CreateDownload(); // Closes the notification. @@ -712,7 +760,13 @@ EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id())); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadRemoved) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadRemoved DISABLED_DownloadRemoved +#else +#define MAYBE_DownloadRemoved DownloadRemoved +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_DownloadRemoved) { CreateDownload(); NotificationRemoveObserver notification_close_observer; @@ -728,7 +782,13 @@ EXPECT_EQ(0u, downloads.size()); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadMultipleFiles) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadMultipleFiles DISABLED_DownloadMultipleFiles +#else +#define MAYBE_DownloadMultipleFiles DownloadMultipleFiles +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_DownloadMultipleFiles) { GURL url1(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); GURL url2(net::URLRequestSlowDownloadJob::kKnownSizeUrl); @@ -860,8 +920,14 @@ GetNotification(notification_id2)->type()); } +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadMultipleFilesOneByOne DISABLED_DownloadMultipleFilesOneByOne +#else +#define MAYBE_DownloadMultipleFilesOneByOne DownloadMultipleFilesOneByOne +#endif IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, - DownloadMultipleFilesOneByOne) { + MAYBE_DownloadMultipleFilesOneByOne) { CreateDownload(); content::DownloadItem* first_download_item = download_item(); content::DownloadItem* second_download_item = nullptr; @@ -937,7 +1003,13 @@ EXPECT_EQ(2u, GetMessageCenter()->GetVisibleNotifications().size()); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, CancelDownload) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_CancelDownload DISABLED_CancelDownload +#else +#define MAYBE_CancelDownload CancelDownload +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_CancelDownload) { CreateDownload(); // Opens the message center. @@ -956,8 +1028,14 @@ EXPECT_EQ(content::DownloadItem::CANCELLED, downloads[0]->GetState()); } +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadCancelledByUserExternally DISABLED_DownloadCancelledByUserExternally +#else +#define MAYBE_DownloadCancelledByUserExternally DownloadCancelledByUserExternally +#endif IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, - DownloadCancelledByUserExternally) { + MAYBE_DownloadCancelledByUserExternally) { CreateDownload(); // Cancels the notification by clicking the "cancel' button. @@ -973,8 +1051,14 @@ EXPECT_EQ(content::DownloadItem::CANCELLED, downloads[0]->GetState()); } +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_DownloadCancelledExternally DISABLED_DownloadCancelledExternally +#else +#define MAYBE_DownloadCancelledExternally DownloadCancelledExternally +#endif IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, - DownloadCancelledExternally) { + MAYBE_DownloadCancelledExternally) { CreateDownload(); // Cancels the notification by clicking the "cancel' button. @@ -990,7 +1074,13 @@ EXPECT_EQ(content::DownloadItem::CANCELLED, downloads[0]->GetState()); } -IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, IncognitoDownloadFile) { +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_IncognitoDownloadFile DISABLED_IncognitoDownloadFile +#else +#define MAYBE_IncognitoDownloadFile IncognitoDownloadFile +#endif +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, MAYBE_IncognitoDownloadFile) { PrepareIncognitoBrowser(); // Starts an incognito download. @@ -1039,8 +1129,14 @@ chrome::CloseWindow(incognito_browser()); } +// TODO(yoshiki): Disabled due to crbug.com/560329 +#if defined(OS_CHROMEOS) +#define MAYBE_SimultaneousIncognitoAndNormalDownloads DISABLED_SimultaneousIncognitoAndNormalDownloads +#else +#define MAYBE_SimultaneousIncognitoAndNormalDownloads SimultaneousIncognitoAndNormalDownloads +#endif IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, - SimultaneousIncognitoAndNormalDownloads) { + MAYBE_SimultaneousIncognitoAndNormalDownloads) { PrepareIncognitoBrowser(); GURL url_incognito(net::URLRequestSlowDownloadJob::kUnknownSizeUrl);
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index c093041..24b8224 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -44,6 +44,7 @@ "//chrome/common/safe_browsing:proto", "//chrome/installer/util", "//components/copresence", + "//components/data_reduction_proxy/proto:data_reduction_proxy_proto", "//components/dom_distiller/core", "//components/onc", "//components/proximity_auth",
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc index 8b6fdff..d7a163ee 100644 --- a/chrome/browser/extensions/api/automation/automation_apitest.cc +++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -124,6 +124,13 @@ << message_; } +IN_PROC_BROWSER_TEST_F(AutomationApiTest, BoundsForRange) { + StartEmbeddedTestServer(); + ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", + "bounds_for_range.html")) + << message_; +} + IN_PROC_BROWSER_TEST_F(AutomationApiTest, TabsAutomationBooleanPermissions) { StartEmbeddedTestServer(); ASSERT_TRUE(RunExtensionSubtest(
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 89356e9..0620287 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -61,6 +61,8 @@ s_whitelist = new PrefsUtil::TypedPrefMap(); (*s_whitelist)["alternate_error_pages.enabled"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)["autofill.enabled"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["bookmark_bar.show_on_all_tabs"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["browser.show_home_button"] = @@ -78,6 +80,8 @@ settings_private::PrefType::PREF_TYPE_STRING; (*s_whitelist)["net.network_prediction_options"] = settings_private::PrefType::PREF_TYPE_NUMBER; + (*s_whitelist)["profile.password_manager_enabled"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["safebrowsing.enabled"] = settings_private::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)["safebrowsing.extended_reporting_enabled"] =
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 45524672..debbdf50 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/login/login_prompt.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/extensions/extension_process_policy.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" @@ -379,7 +380,8 @@ listener_result.Reset(); listener_main2.Reply(""); EXPECT_TRUE(listener_result.WaitUntilSatisfied()); - if (content::AreAllSitesIsolatedForTesting()) { + if (content::AreAllSitesIsolatedForTesting() || + extensions::IsIsolateExtensionsEnabled()) { // With --site-per-process, the extension frame does run in the extension's // process. EXPECT_EQ("Intercepted requests: ?contentscript",
diff --git a/chrome/browser/extensions/extension_loading_browsertest.cc b/chrome/browser/extensions/extension_loading_browsertest.cc index 4e82ad16..3c55c65 100644 --- a/chrome/browser/extensions/extension_loading_browsertest.cc +++ b/chrome/browser/extensions/extension_loading_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/version.h" +#include "base/win/windows_version.h" #include "chrome/browser/extensions/devtools_util.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_service.h" @@ -97,6 +98,12 @@ // Tests the behavior described in http://crbug.com/532088. IN_PROC_BROWSER_TEST_F(ExtensionLoadingTest, KeepAliveWithDevToolsOpenOnReload) { +#if defined(OS_WIN) + // Flaky on Win XP SP3. http://crbug.com/560716. + if (base::win::GetVersion() <= base::win::VERSION_SERVER_2003) + return; +#endif + embedded_test_server()->ServeFilesFromDirectory( base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc index ef9ab802..a7ca271 100644 --- a/chrome/browser/extensions/tab_helper.cc +++ b/chrome/browser/extensions/tab_helper.cc
@@ -395,10 +395,7 @@ return_route_id); scoped_refptr<WebstoreInlineInstaller> installer( webstore_inline_installer_factory_->CreateInstaller( - web_contents(), - webstore_item_id, - requestor_url, - callback)); + web_contents(), host, webstore_item_id, requestor_url, callback)); installer->BeginInstall(); } }
diff --git a/chrome/browser/extensions/webstore_inline_installer.cc b/chrome/browser/extensions/webstore_inline_installer.cc index 045d996..e0eaf43 100644 --- a/chrome/browser/extensions/webstore_inline_installer.cc +++ b/chrome/browser/extensions/webstore_inline_installer.cc
@@ -7,6 +7,7 @@ #include "base/strings/stringprintf.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" +#include "content/public/browser/navigation_details.h" #include "content/public/browser/web_contents.h" using content::WebContents; @@ -29,6 +30,7 @@ WebstoreInlineInstaller::WebstoreInlineInstaller( content::WebContents* web_contents, + content::RenderFrameHost* host, const std::string& webstore_item_id, const GURL& requestor_url, const Callback& callback) @@ -37,8 +39,8 @@ Profile::FromBrowserContext(web_contents->GetBrowserContext()), callback), content::WebContentsObserver(web_contents), - requestor_url_(requestor_url) { -} + host_(host), + requestor_url_(requestor_url) {} WebstoreInlineInstaller::~WebstoreInlineInstaller() {} @@ -91,8 +93,8 @@ } bool WebstoreInlineInstaller::CheckRequestorAlive() const { - // The tab may have gone away - cancel installation in that case. - return web_contents() != NULL; + // The frame or tab may have gone away - cancel installation in that case. + return host_ != nullptr && web_contents() != nullptr; } const GURL& WebstoreInlineInstaller::GetRequestorURL() const { @@ -176,6 +178,15 @@ // Private implementation. // +void WebstoreInlineInstaller::DidNavigateAnyFrame( + content::RenderFrameHost* render_frame_host, + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + if (!details.is_in_page && + (render_frame_host == host_ || details.is_main_frame)) + host_ = nullptr; +} + void WebstoreInlineInstaller::WebContentsDestroyed() { AbortInstall(); }
diff --git a/chrome/browser/extensions/webstore_inline_installer.h b/chrome/browser/extensions/webstore_inline_installer.h index 583a6c351..573e7d6 100644 --- a/chrome/browser/extensions/webstore_inline_installer.h +++ b/chrome/browser/extensions/webstore_inline_installer.h
@@ -31,6 +31,7 @@ typedef WebstoreStandaloneInstaller::Callback Callback; WebstoreInlineInstaller(content::WebContents* web_contents, + content::RenderFrameHost* host, const std::string& webstore_item_id, const GURL& requestor_url, const Callback& callback); @@ -61,6 +62,9 @@ private: // content::WebContentsObserver interface implementation. + void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host, + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) override; void WebContentsDestroyed() override; // Checks whether the install is initiated by a page in a verified site @@ -68,6 +72,8 @@ static bool IsRequestorURLInVerifiedSite(const GURL& requestor_url, const std::string& verified_site); + // This corresponds to the frame that initiated the install request. + content::RenderFrameHost* host_; GURL requestor_url_; DISALLOW_IMPLICIT_CONSTRUCTORS(WebstoreInlineInstaller);
diff --git a/chrome/browser/extensions/webstore_inline_installer_browsertest.cc b/chrome/browser/extensions/webstore_inline_installer_browsertest.cc index 9014479..7d29675 100644 --- a/chrome/browser/extensions/webstore_inline_installer_browsertest.cc +++ b/chrome/browser/extensions/webstore_inline_installer_browsertest.cc
@@ -18,6 +18,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test_utils.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "url/gurl.h" @@ -35,6 +36,14 @@ const char kTestDataPath[] = "extensions/api_test/webstore_inline_install"; const char kCrxFilename[] = "extension.crx"; +// A struct for letting us store the actual parameters that were passed to +// the install callback. +struct InstallResult { + bool success = false; + std::string error; + webstore_install::Result result = webstore_install::RESULT_LAST; +}; + } // namespace class WebstoreInlineInstallerTest : public WebstoreInstallerTest { @@ -87,46 +96,82 @@ class WebstoreInlineInstallerForTest : public WebstoreInlineInstaller { public: WebstoreInlineInstallerForTest(WebContents* contents, + content::RenderFrameHost* host, const std::string& extension_id, const GURL& requestor_url, const Callback& callback) : WebstoreInlineInstaller( contents, + host, kTestExtensionId, requestor_url, - base::Bind(DummyCallback)), - programmable_prompt_(NULL) { - } + base::Bind(&WebstoreInlineInstallerForTest::InstallCallback, + base::Unretained(this))), + install_result_target_(nullptr), + programmable_prompt_(nullptr) {} scoped_ptr<ExtensionInstallPrompt> CreateInstallUI() override { programmable_prompt_ = new ProgrammableInstallPrompt(web_contents()); return make_scoped_ptr(programmable_prompt_); } + // Added here to make it public so that test cases can call it below. + bool CheckRequestorAlive() const override { + return WebstoreInlineInstaller::CheckRequestorAlive(); + } + + // Tests that care about the actual arguments to the install callback can use + // this to receive a copy in |install_result_target|. + void set_install_result_target( + scoped_ptr<InstallResult>* install_result_target) { + install_result_target_ = install_result_target; + } + private: ~WebstoreInlineInstallerForTest() override {} friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>; - static void DummyCallback(bool success, - const std::string& error, - webstore_install::Result result) { + void InstallCallback(bool success, + const std::string& error, + webstore_install::Result result) { + if (install_result_target_) { + install_result_target_->reset(new InstallResult); + (*install_result_target_)->success = success; + (*install_result_target_)->error = error; + (*install_result_target_)->result = result; + } } + // This can be set by tests that want to get the actual install callback + // arguments. + scoped_ptr<InstallResult>* install_result_target_; + ProgrammableInstallPrompt* programmable_prompt_; }; class WebstoreInlineInstallerForTestFactory : public WebstoreInlineInstallerFactory { + public: + WebstoreInlineInstallerForTestFactory() : last_installer_(nullptr) {} ~WebstoreInlineInstallerForTestFactory() override {} + + WebstoreInlineInstallerForTest* last_installer() { return last_installer_; } + WebstoreInlineInstaller* CreateInstaller( WebContents* contents, + content::RenderFrameHost* host, const std::string& webstore_item_id, const GURL& requestor_url, const WebstoreStandaloneInstaller::Callback& callback) override { - return new WebstoreInlineInstallerForTest( - contents, webstore_item_id, requestor_url, callback); + last_installer_ = new WebstoreInlineInstallerForTest( + contents, host, webstore_item_id, requestor_url, callback); + return last_installer_; } + + private: + // The last installer that was created. + WebstoreInlineInstallerForTest* last_installer_; }; IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, @@ -145,6 +190,42 @@ ProgrammableInstallPrompt::Accept(); } +IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, + NavigateBeforeInstallConfirmation) { + GURL install_url = GenerateTestServerUrl(kAppDomain, "install.html"); + ui_test_utils::NavigateToURL(browser(), install_url); + WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); + WebstoreInlineInstallerForTestFactory* factory = + new WebstoreInlineInstallerForTestFactory(); + tab_helper->SetWebstoreInlineInstallerFactoryForTests(factory); + RunTestAsync("runTest"); + while (!ProgrammableInstallPrompt::Ready()) + base::RunLoop().RunUntilIdle(); + GURL new_url = GenerateTestServerUrl(kNonAppDomain, "empty.html"); + web_contents->GetController().LoadURL( + new_url, content::Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + EXPECT_TRUE(content::WaitForLoadStop(web_contents)); + ASSERT_NE(factory->last_installer(), nullptr); + EXPECT_NE(factory->last_installer()->web_contents(), nullptr); + EXPECT_FALSE(factory->last_installer()->CheckRequestorAlive()); + + // Right now the way we handle navigations away from the frame that began the + // inline install is to just declare the requestor to be dead, but not to + // kill the prompt (that would be a better UX, but more complicated to + // implement). If we ever do change things to kill the prompt in this case, + // the following code can be removed (it verifies that clicking ok on the + // dialog does not result in an install). + scoped_ptr<InstallResult> install_result; + factory->last_installer()->set_install_result_target(&install_result); + ASSERT_TRUE(ProgrammableInstallPrompt::Ready()); + ProgrammableInstallPrompt::Accept(); + ASSERT_NE(install_result.get(), nullptr); + EXPECT_EQ(install_result->success, false); + EXPECT_EQ(install_result->result, webstore_install::ABORTED); +} + // Flaky: https://crbug.com/537526. IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest, DISABLED_ShouldBlockInlineInstallFromPopupWindow) {
diff --git a/chrome/browser/extensions/webstore_inline_installer_factory.cc b/chrome/browser/extensions/webstore_inline_installer_factory.cc index 06f4592..e96b725 100644 --- a/chrome/browser/extensions/webstore_inline_installer_factory.cc +++ b/chrome/browser/extensions/webstore_inline_installer_factory.cc
@@ -10,12 +10,13 @@ namespace extensions { WebstoreInlineInstaller* WebstoreInlineInstallerFactory::CreateInstaller( - content::WebContents* contents, - const std::string& webstore_item_id, - const GURL& requestor_url, - const WebstoreStandaloneInstaller::Callback& callback) { - return new WebstoreInlineInstaller( - contents, webstore_item_id, requestor_url, callback); + content::WebContents* contents, + content::RenderFrameHost* host, + const std::string& webstore_item_id, + const GURL& requestor_url, + const WebstoreStandaloneInstaller::Callback& callback) { + return new WebstoreInlineInstaller(contents, host, webstore_item_id, + requestor_url, callback); } } // namespace extensions
diff --git a/chrome/browser/extensions/webstore_inline_installer_factory.h b/chrome/browser/extensions/webstore_inline_installer_factory.h index b125741..5b891cc 100644 --- a/chrome/browser/extensions/webstore_inline_installer_factory.h +++ b/chrome/browser/extensions/webstore_inline_installer_factory.h
@@ -12,7 +12,7 @@ #include "chrome/browser/extensions/webstore_standalone_installer.h" namespace content { - class WebContents; +class WebContents; } class GURL; @@ -28,6 +28,7 @@ // Create a new WebstoreInlineInstallerInstance to be owned by the caller. virtual WebstoreInlineInstaller* CreateInstaller( content::WebContents* contents, + content::RenderFrameHost* host, const std::string& webstore_item_id, const GURL& requestor_url, const WebstoreStandaloneInstaller::Callback& callback);
diff --git a/chrome/browser/extensions/webstore_inline_installer_unittest.cc b/chrome/browser/extensions/webstore_inline_installer_unittest.cc index d415be25b..ae45287 100644 --- a/chrome/browser/extensions/webstore_inline_installer_unittest.cc +++ b/chrome/browser/extensions/webstore_inline_installer_unittest.cc
@@ -39,6 +39,7 @@ content::WebContents* contents, const std::string& requestor_url) : WebstoreInlineInstaller(contents, + contents->GetMainFrame(), "", GURL(requestor_url), base::Bind(&TestInstallerCallback)) {
diff --git a/chrome/browser/interstitials/chrome_controller_client.cc b/chrome/browser/interstitials/chrome_controller_client.cc new file mode 100644 index 0000000..01c1be72 --- /dev/null +++ b/chrome/browser/interstitials/chrome_controller_client.cc
@@ -0,0 +1,40 @@ +// Copyright 2015 The Chromium Authors. 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/interstitials/chrome_controller_client.h" + +#include "base/prefs/pref_service.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/referrer.h" + +using content::Referrer; + +ChromeControllerClient::ChromeControllerClient( + content::WebContents* web_contents) + : web_contents_(web_contents) {} + +ChromeControllerClient::~ChromeControllerClient() {} + +void ChromeControllerClient::OpenUrlInCurrentTab(const GURL& url) { + content::OpenURLParams params(url, Referrer(), CURRENT_TAB, + ui::PAGE_TRANSITION_LINK, false); + web_contents_->OpenURL(params); +} + +const std::string& ChromeControllerClient::GetApplicationLocale() { + return g_browser_process->GetApplicationLocale(); +} + +PrefService* ChromeControllerClient::GetPrefService() { + Profile* profile = + Profile::FromBrowserContext(web_contents_->GetBrowserContext()); + return profile->GetPrefs(); +} + +const std::string ChromeControllerClient::GetExtendedReportingPrefName() { + return prefs::kSafeBrowsingExtendedReportingEnabled; +}
diff --git a/chrome/browser/interstitials/chrome_controller_client.h b/chrome/browser/interstitials/chrome_controller_client.h new file mode 100644 index 0000000..3634233 --- /dev/null +++ b/chrome/browser/interstitials/chrome_controller_client.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 CHROME_BROWSER_INTERSTITIALS_CHROME_CONTROLLER_CLIENT_H_ +#define CHROME_BROWSER_INTERSTITIALS_CHROME_CONTROLLER_CLIENT_H_ + +#include "base/macros.h" +#include "components/security_interstitials/core/controller_client.h" + +namespace content { +class WebContents; +} + +// Provides embedder-specific logic for the security error page controller. +class ChromeControllerClient : public security_interstitials::ControllerClient { + public: + explicit ChromeControllerClient(content::WebContents* web_contents); + ~ChromeControllerClient() override; + + protected: + // security_interstitials::ControllerClient overrides + void OpenUrlInCurrentTab(const GURL& url) override; + const std::string& GetApplicationLocale() override; + PrefService* GetPrefService() override; + const std::string GetExtendedReportingPrefName() override; + + private: + content::WebContents* web_contents_; + + DISALLOW_COPY_AND_ASSIGN(ChromeControllerClient); +}; + +#endif // CHROME_BROWSER_INTERSTITIALS_CHROME_CONTROLLER_CLIENT_H_
diff --git a/chrome/browser/interstitials/security_interstitial_page.cc b/chrome/browser/interstitials/security_interstitial_page.cc index d476177..fd26268 100644 --- a/chrome/browser/interstitials/security_interstitial_page.cc +++ b/chrome/browser/interstitials/security_interstitial_page.cc
@@ -11,12 +11,11 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/net/referrer.h" +#include "chrome/browser/interstitials/chrome_controller_client.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" -#include "components/google/core/browser/google_util.h" #include "components/grit/components_resources.h" #include "components/security_interstitials/core/metrics_helper.h" #include "components/url_formatter/url_formatter.h" @@ -28,25 +27,14 @@ #include "ui/base/webui/jstemplate_builder.h" #include "ui/base/webui/web_ui_util.h" -namespace interstitials { -const char kBoxChecked[] = "boxchecked"; -const char kDisplayCheckBox[] = "displaycheckbox"; -const char kOptInLink[] = "optInLink"; -const char kPrivacyLinkHtml[] = - "<a id=\"privacy-link\" href=\"\" onclick=\"sendCommand(%d); " - "return false;\" onmousedown=\"return false;\">%s</a>"; -} - -using content::OpenURLParams; -using content::Referrer; - SecurityInterstitialPage::SecurityInterstitialPage( content::WebContents* web_contents, const GURL& request_url) : web_contents_(web_contents), request_url_(request_url), interstitial_page_(NULL), - create_view_(true) { + create_view_(true), + controller_(new ChromeControllerClient(web_contents)) { // Creating interstitial_page_ without showing it leaks memory, so don't // create it here. } @@ -110,22 +98,20 @@ return webui::GetI18nTemplateHtml(html, &load_time_data); } -void SecurityInterstitialPage::OpenUrlInCurrentTab(const GURL& url) { - OpenURLParams params(url, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_LINK, - false); - web_contents()->OpenURL(params); +void SecurityInterstitialPage::SetReportingPreference(bool report) { + controller_->SetReportingPreference(report); } -const std::string& SecurityInterstitialPage::GetApplicationLocale() { - return g_browser_process->GetApplicationLocale(); +void SecurityInterstitialPage::OpenExtendedReportingPrivacyPolicy() { + controller_->OpenExtendedReportingPrivacyPolicy(); } -PrefService* SecurityInterstitialPage::GetPrefService() { - Profile* profile = - Profile::FromBrowserContext(web_contents()->GetBrowserContext()); - return profile->GetPrefs(); +security_interstitials::MetricsHelper* +SecurityInterstitialPage::metrics_helper() { + return controller_->metrics_helper(); } -const std::string SecurityInterstitialPage::GetExtendedReportingPrefName() { - return prefs::kSafeBrowsingExtendedReportingEnabled; +void SecurityInterstitialPage::set_metrics_helper( + scoped_ptr<security_interstitials::MetricsHelper> metrics_helper) { + controller_->set_metrics_helper(metrics_helper.Pass()); }
diff --git a/chrome/browser/interstitials/security_interstitial_page.h b/chrome/browser/interstitials/security_interstitial_page.h index 215253eb..914e096d 100644 --- a/chrome/browser/interstitials/security_interstitial_page.h +++ b/chrome/browser/interstitials/security_interstitial_page.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_INTERSTITIALS_SECURITY_INTERSTITIAL_PAGE_H_ #include "base/strings/string16.h" -#include "components/security_interstitials/core/controller_client.h" #include "content/public/browser/interstitial_page_delegate.h" #include "url/gurl.h" @@ -19,17 +18,13 @@ class WebContents; } -namespace interstitials { -// Constants used to communicate with the JavaScript. -extern const char kBoxChecked[]; -extern const char kDisplayCheckBox[]; -extern const char kOptInLink[]; -extern const char kPrivacyLinkHtml[]; +namespace security_interstitials { +class MetricsHelper; } -class SecurityInterstitialPage - : public content::InterstitialPageDelegate, - public security_interstitials::ControllerClient { +class ChromeControllerClient; + +class SecurityInterstitialPage : public content::InterstitialPageDelegate { public: SecurityInterstitialPage(content::WebContents* web_contents, const GURL& url); @@ -63,12 +58,14 @@ // Profile associated with |web_contents_|. bool IsPrefEnabled(const char* pref); - protected: - // security_interstitials::ControllerClient overrides - void OpenUrlInCurrentTab(const GURL& url) override; - const std::string& GetApplicationLocale() override; - PrefService* GetPrefService() override; - const std::string GetExtendedReportingPrefName() override; + // TODO(felt): Remove these. They are temporary methods, used to pass along + // calls to the |controller_| for subclasses that don't yet have their own + // ChromeControllerClients. crbug.com/488673 + void SetReportingPreference(bool report); + void OpenExtendedReportingPrivacyPolicy(); + security_interstitials::MetricsHelper* metrics_helper(); + void set_metrics_helper( + scoped_ptr<security_interstitials::MetricsHelper> metrics_helper); private: // The WebContents with which this interstitial page is @@ -81,6 +78,8 @@ content::InterstitialPage* interstitial_page_; // Whether the interstitial should create a view. bool create_view_; + // For subclasses that don't have their own ChromeControllerClients yet. + scoped_ptr<ChromeControllerClient> controller_; DISALLOW_COPY_AND_ASSIGN(SecurityInterstitialPage); };
diff --git a/chrome/browser/interstitials/security_interstitial_page_test_utils.cc b/chrome/browser/interstitials/security_interstitial_page_test_utils.cc index 5c224c3..1ca8f51 100644 --- a/chrome/browser/interstitials/security_interstitial_page_test_utils.cc +++ b/chrome/browser/interstitials/security_interstitial_page_test_utils.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/pref_names.h" +#include "components/security_interstitials/core/controller_client.h" #include "content/public/browser/interstitial_page.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" @@ -31,12 +32,12 @@ std::string command = base::StringPrintf( "var hasText = document.body.textContent.indexOf('%s') >= 0;" "window.domAutomationController.send(hasText ? %d : %d);", - text.c_str(), SecurityInterstitialPage::CMD_TEXT_FOUND, - SecurityInterstitialPage::CMD_TEXT_NOT_FOUND); + text.c_str(), security_interstitials::CMD_TEXT_FOUND, + security_interstitials::CMD_TEXT_NOT_FOUND); int result = 0; EXPECT_TRUE(content::ExecuteScriptAndExtractInt(interstitial->GetMainFrame(), command, &result)); - return result == SecurityInterstitialPage::CMD_TEXT_FOUND; + return result == security_interstitials::CMD_TEXT_FOUND; } void SecurityInterstitialIDNTest::SetUpOnMainThread() {
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 1f0d5f9..e56b75ab 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -42,7 +42,6 @@ #include "chrome/common/pref_names.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.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_usage/core/data_use_aggregator.h" #include "components/data_usage/core/data_use_amortizer.h" #include "components/data_usage/core/data_use_annotator.h" @@ -689,7 +688,7 @@ tracked_objects::ScopedTracker tracking_profile8( FROM_HERE_WITH_EXPLICIT_FUNCTION( "466432 IOThread::InitAsync::CreateLogVerifiers::Start")); - std::vector<scoped_refptr<net::CTLogVerifier>> ct_logs( + std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs( net::ct::CreateLogVerifiersForKnownLogs()); // Add logs from command line @@ -708,7 +707,7 @@ std::string ct_public_key_data; CHECK(base::Base64Decode(log_metadata[1], &ct_public_key_data)) << "Unable to decode CT public key."; - scoped_refptr<net::CTLogVerifier> external_log_verifier( + scoped_refptr<const net::CTLogVerifier> external_log_verifier( net::CTLogVerifier::Create(ct_public_key_data, log_description, log_url)); CHECK(external_log_verifier) << "Unable to parse CT public key."; @@ -717,6 +716,8 @@ } } + globals_->ct_logs.assign(ct_logs.begin(), ct_logs.end()); + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432 // is fixed. tracked_objects::ScopedTracker tracking_profile9( @@ -730,7 +731,7 @@ net::MultiLogCTVerifier* ct_verifier = new net::MultiLogCTVerifier(); globals_->cert_transparency_verifier.reset(ct_verifier); // Add built-in logs - ct_verifier->AddLogs(ct_logs); + ct_verifier->AddLogs(globals_->ct_logs); // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432 // is fixed. @@ -1011,8 +1012,6 @@ registry->RegisterStringPref(prefs::kGSSAPILibraryName, std::string()); registry->RegisterStringPref(prefs::kAuthAndroidNegotiateAccountType, std::string()); - registry->RegisterStringPref( - data_reduction_proxy::prefs::kDataReductionProxy, std::string()); registry->RegisterBooleanPref(prefs::kEnableReferrers, true); data_reduction_proxy::RegisterPrefs(registry); registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, true);
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 41c042f..19e08f1 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -60,7 +60,7 @@ class CertVerifier; class ChannelIDService; class CookieStore; -class CTVerifier; +class CTLogVerifier; class FtpTransactionFactory; class HostMappingRules; class HostResolver; @@ -153,6 +153,7 @@ // used to enforce pinning for system requests and will only use built-in // pins. scoped_ptr<net::TransportSecurityState> transport_security_state; + std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs; scoped_ptr<net::CTVerifier> cert_transparency_verifier; scoped_ptr<net::CertPolicyEnforcer> cert_policy_enforcer; scoped_refptr<net::SSLConfigService> ssl_config_service;
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac.mm b/chrome/browser/local_discovery/service_discovery_client_mac.mm index 7837234..1c7cd4a 100644 --- a/chrome/browser/local_discovery/service_discovery_client_mac.mm +++ b/chrome/browser/local_discovery/service_discovery_client_mac.mm
@@ -352,6 +352,7 @@ if (end_point.FromSockAddr(socket, length)) { service_description_.address = net::HostPortPair::FromIPEndPoint(end_point); + service_description_.ip_address = end_point.address(); break; } }
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm b/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm index dc0f20f..ccb10856 100644 --- a/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm +++ b/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm
@@ -147,8 +147,9 @@ EXPECT_EQ(1, num_resolves_); EXPECT_EQ(2u, last_service_description_.metadata.size()); - EXPECT_EQ(kIp, last_service_description_.address.host()); + EXPECT_EQ(ip_address, last_service_description_.ip_address); EXPECT_EQ(kPort, last_service_description_.address.port()); + EXPECT_EQ(kIp, last_service_description_.address.host()); } } // namespace local_discovery
diff --git a/chrome/browser/media/webrtc_browsertest_audio.cc b/chrome/browser/media/webrtc_browsertest_audio.cc index 1f7defec..cf6a9cc 100644 --- a/chrome/browser/media/webrtc_browsertest_audio.cc +++ b/chrome/browser/media/webrtc_browsertest_audio.cc
@@ -16,8 +16,8 @@ // bluntly trigger CHECKs if we can't read the file or if it's malformed. The // caller takes ownership of the returned data. The size of the data is stored // in |read_length|. -scoped_ptr<uint8[]> ReadWavFile(const base::FilePath& wav_filename, - size_t* file_length) { +scoped_ptr<char[]> ReadWavFile(const base::FilePath& wav_filename, + size_t* file_length) { base::File wav_file( wav_filename, base::File::FLAG_OPEN | base::File::FLAG_READ); if (!wav_file.IsValid()) { @@ -27,28 +27,15 @@ size_t wav_file_length = wav_file.GetLength(); - uint8* wav_file_data = new uint8[wav_file_length]; - size_t read_bytes = wav_file.Read(0, reinterpret_cast<char*>(wav_file_data), - wav_file_length); + scoped_ptr<char[]> data(new char[wav_file_length]); + size_t read_bytes = wav_file.Read(0, data.get(), wav_file_length); if (read_bytes != wav_file_length) { - CHECK(false) << "Failed to read all bytes of " << wav_filename.value(); + LOG(ERROR) << "Failed to read all bytes of " << wav_filename.value(); return nullptr; } *file_length = wav_file_length; - return scoped_ptr<uint8[]>(wav_file_data); + return data; } - -scoped_ptr<media::WavAudioHandler> CreateWavAudioHandler( - const base::FilePath& wav_filename, const uint8* wav_file_data, - size_t wav_file_length) { - base::StringPiece wav_data(reinterpret_cast<const char*>(wav_file_data), - wav_file_length); - scoped_ptr<media::WavAudioHandler> wav_audio_handler( - new media::WavAudioHandler(wav_data)); - - return wav_audio_handler.Pass(); -} - } // namespace namespace test { @@ -57,9 +44,9 @@ media::AudioParameters* file_parameters) { // Read the file, and put its data in a scoped_ptr so it gets deleted later. size_t file_length = 0; - scoped_ptr<uint8[]> wav_file_data = ReadWavFile(wav_filename, &file_length); - scoped_ptr<media::WavAudioHandler> wav_audio_handler = CreateWavAudioHandler( - wav_filename, wav_file_data.get(), file_length); + scoped_ptr<char[]> wav_file_data = ReadWavFile(wav_filename, &file_length); + auto wav_audio_handler = media::WavAudioHandler::Create( + base::StringPiece(wav_file_data.get(), file_length)); scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create( wav_audio_handler->num_channels(), wav_audio_handler->total_frames());
diff --git a/chrome/browser/media/webrtc_rtp_dump_handler_unittest.cc b/chrome/browser/media/webrtc_rtp_dump_handler_unittest.cc index 23a0a4f..6fefb3f 100644 --- a/chrome/browser/media/webrtc_rtp_dump_handler_unittest.cc +++ b/chrome/browser/media/webrtc_rtp_dump_handler_unittest.cc
@@ -42,17 +42,17 @@ void EndDump(RtpDumpType type, const EndDumpCallback& finished_callback) override { - bool incoming_sucess = end_dump_success_; + bool incoming_success = end_dump_success_; bool outgoing_success = end_dump_success_; if (type == RTP_DUMP_INCOMING) outgoing_success = false; else if (type == RTP_DUMP_OUTGOING) - incoming_sucess = false; + incoming_success = false; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(finished_callback, incoming_sucess, outgoing_success)); + base::Bind(finished_callback, incoming_success, outgoing_success)); } private:
diff --git a/chrome/browser/media_galleries/android/mtp_device_delegate_impl_android.cc b/chrome/browser/media_galleries/android/mtp_device_delegate_impl_android.cc new file mode 100644 index 0000000..0c15fc8 --- /dev/null +++ b/chrome/browser/media_galleries/android/mtp_device_delegate_impl_android.cc
@@ -0,0 +1,17 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h" + +void CreateMTPDeviceAsyncDelegate( + const std::string& device_location, + const bool read_only, + const CreateMTPDeviceAsyncDelegateCallback& callback) { + // Return nullptr as there is no MTPDeviceAsyncDelegate implementation for + // Chrome on Android at the moment. + // TODO(crbug.com/560390): Add an MTPDeviceAsyncDelegate implementation on + // Android. + NOTIMPLEMENTED(); + callback.Run(nullptr); +}
diff --git a/chrome/browser/media_galleries/media_folder_finder.cc b/chrome/browser/media_galleries/media_folder_finder.cc index 26ec50eb..0a14c221 100644 --- a/chrome/browser/media_galleries/media_folder_finder.cc +++ b/chrome/browser/media_galleries/media_folder_finder.cc
@@ -56,6 +56,9 @@ #if defined(OS_WIN) || defined(OS_LINUX) base::DIR_TEMP, #endif +#if defined(OS_ANDROID) + base::DIR_ANDROID_APP_DATA, +#endif }; bool IsValidScanPath(const base::FilePath& path) {
diff --git a/chrome/browser/net/net_error_tab_helper.cc b/chrome/browser/net/net_error_tab_helper.cc index a0e73cf..25b9e7a950 100644 --- a/chrome/browser/net/net_error_tab_helper.cc +++ b/chrome/browser/net/net_error_tab_helper.cc
@@ -13,18 +13,25 @@ #include "chrome/browser/net/net_error_diagnostics_dialog.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/localized_error.h" #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" #include "components/error_page/common/net_error_info.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "ipc/ipc_message_macros.h" #include "net/base/net_errors.h" #include "url/gurl.h" #if defined(OS_ANDROID) +#include "chrome/browser/android/offline_pages/offline_page_model_factory.h" #include "chrome/browser/android/tab_android.h" -#endif +#include "components/offline_pages/offline_page_feature.h" +#include "components/offline_pages/offline_page_item.h" +#include "components/offline_pages/offline_page_model.h" +#endif // defined(OS_ANDROID) using content::BrowserContext; using content::BrowserThread; @@ -32,6 +39,7 @@ using content::WebContentsObserver; using error_page::DnsProbeStatus; using error_page::DnsProbeStatusToString; +using error_page::OfflinePageStatus; using ui::PageTransition; DEFINE_WEB_CONTENTS_USER_DATA_KEY(chrome_browser_net::NetErrorTabHelper); @@ -124,8 +132,8 @@ is_error_page_ = is_error_page; #if defined(OS_ANDROID) - SetHasOfflinePages(render_frame_host); -#endif + SetOfflinePageInfo(render_frame_host, validated_url); +#endif // defined(OS_ANDROID) } void NetErrorTabHelper::DidCommitProvisionalLoadForFrame( @@ -171,13 +179,16 @@ bool NetErrorTabHelper::OnMessageReceived( const IPC::Message& message, content::RenderFrameHost* render_frame_host) { + if (render_frame_host != web_contents()->GetMainFrame()) + return false; bool handled = true; IPC_BEGIN_MESSAGE_MAP(NetErrorTabHelper, message) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RunNetworkDiagnostics, RunNetworkDiagnostics) #if defined(OS_ANDROID) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ShowOfflinePages, ShowOfflinePages) -#endif + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_LoadOfflineCopy, LoadOfflineCopy) +#endif // defined(OS_ANDROID) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -286,23 +297,63 @@ } #if defined(OS_ANDROID) -void NetErrorTabHelper::SetHasOfflinePages( - content::RenderFrameHost* render_frame_host) { - DCHECK(web_contents()); - TabAndroid* tab = TabAndroid::FromWebContents(web_contents()); - bool has_offline_pages = tab && tab->HasOfflinePages(); - render_frame_host->Send( - new ChromeViewMsg_SetHasOfflinePages( - render_frame_host->GetRoutingID(), - has_offline_pages)); +void NetErrorTabHelper::SetOfflinePageInfo( + content::RenderFrameHost* render_frame_host, + const GURL& url) { + // Bails out if offline pages not supported. + if (!offline_pages::IsOfflinePagesEnabled()) + return; + + offline_pages::OfflinePageModel* offline_page_model = + offline_pages::OfflinePageModelFactory::GetForBrowserContext( + web_contents()->GetBrowserContext()); + if (!offline_page_model) + return; + + OfflinePageStatus status = OfflinePageStatus::NONE; + if (offline_page_model->HasOfflinePages()) { + status = offline_page_model->GetPageByOnlineURL(url) + ? OfflinePageStatus::HAS_OFFLINE_PAGE + : OfflinePageStatus::HAS_OTHER_OFFLINE_PAGES; + } + render_frame_host->Send(new ChromeViewMsg_SetOfflinePageInfo( + render_frame_host->GetRoutingID(), status)); } void NetErrorTabHelper::ShowOfflinePages() { + // Makes sure that this is coming from an error page. + if (!IsFromErrorPage()) + return; + DCHECK(web_contents()); TabAndroid* tab = TabAndroid::FromWebContents(web_contents()); if (tab) tab->ShowOfflinePages(); } -#endif + +void NetErrorTabHelper::LoadOfflineCopy(const GURL& url) { + // Makes sure that this is coming from an error page. + if (!IsFromErrorPage()) + return; + + GURL validated_url(url); + if (!validated_url.is_valid()) + return; + + if (validated_url != web_contents()->GetLastCommittedURL()) + return; + + TabAndroid* tab = TabAndroid::FromWebContents(web_contents()); + if (tab) + tab->LoadOfflineCopy(url); +} + +bool NetErrorTabHelper::IsFromErrorPage() const { + content::NavigationEntry* entry = + web_contents()->GetController().GetLastCommittedEntry(); + return entry && (entry->GetPageType() == content::PAGE_TYPE_ERROR); +} + +#endif // defined(OS_ANDROID) } // namespace chrome_browser_net
diff --git a/chrome/browser/net/net_error_tab_helper.h b/chrome/browser/net/net_error_tab_helper.h index ef4b6198..169c81a 100644 --- a/chrome/browser/net/net_error_tab_helper.h +++ b/chrome/browser/net/net_error_tab_helper.h
@@ -104,9 +104,12 @@ // Relates to offline pages handling. #if defined(OS_ANDROID) - void SetHasOfflinePages(content::RenderFrameHost* render_frame_host); + void SetOfflinePageInfo(content::RenderFrameHost* render_frame_host, + const GURL& url); void ShowOfflinePages(); -#endif + void LoadOfflineCopy(const GURL& url); + bool IsFromErrorPage() const; +#endif // defined(OS_ANDROID) // True if the last provisional load that started was for an error page. bool is_error_page_;
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 427a811..02f8cd7 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -118,8 +118,13 @@ return; } - content::RecordAction( - base::UserMetricsAction("Notifications.Persistent.Clicked")); + if (action_index == -1) { + content::RecordAction(base::UserMetricsAction( + "Notifications.Persistent.Clicked")); + } else { + content::RecordAction(base::UserMetricsAction( + "Notifications.Persistent.ClickedActionButton")); + } content::NotificationEventDispatcher::GetInstance() ->DispatchNotificationClickEvent(
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 2af8a6a..9fb2881 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -19,7 +19,7 @@ #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h" -#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" +#include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" @@ -218,8 +218,8 @@ } if (IsTheHotNewBubbleUIEnabled()) { - ManagePasswordsUIController* manage_passwords_ui_controller = - ManagePasswordsUIController::FromWebContents(web_contents()); + PasswordsClientUIDelegate* manage_passwords_ui_controller = + PasswordsClientUIDelegateFromWebContents(web_contents()); if (update_password && IsUpdatePasswordUIEnabled()) { manage_passwords_ui_controller->OnUpdatePasswordSubmitted( form_to_save.Pass()); @@ -248,9 +248,9 @@ ScopedVector<autofill::PasswordForm> federated_forms, const GURL& origin, base::Callback<void(const password_manager::CredentialInfo&)> callback) { - return ManagePasswordsUIController::FromWebContents(web_contents())-> - OnChooseCredentials(local_forms.Pass(), federated_forms.Pass(), origin, - callback); + return PasswordsClientUIDelegateFromWebContents(web_contents()) + ->OnChooseCredentials(local_forms.Pass(), federated_forms.Pass(), origin, + callback); } void ChromePasswordManagerClient::ForceSavePassword() { @@ -265,8 +265,8 @@ #if defined(OS_ANDROID) ShowAutoSigninPrompt(web_contents(), local_forms[0]->username_value); #else - ManagePasswordsUIController::FromWebContents(web_contents())-> - OnAutoSignin(local_forms.Pass()); + PasswordsClientUIDelegateFromWebContents(web_contents()) + ->OnAutoSignin(local_forms.Pass()); #endif } @@ -277,8 +277,8 @@ GeneratedPasswordSavedInfoBarDelegateAndroid::Create(web_contents()); #else if (IsTheHotNewBubbleUIEnabled()) { - ManagePasswordsUIController* manage_passwords_ui_controller = - ManagePasswordsUIController::FromWebContents(web_contents()); + PasswordsClientUIDelegate* manage_passwords_ui_controller = + PasswordsClientUIDelegateFromWebContents(web_contents()); manage_passwords_ui_controller->OnAutomaticPasswordSave( saved_form.Pass()); } @@ -288,8 +288,8 @@ void ChromePasswordManagerClient::PasswordWasAutofilled( const autofill::PasswordFormMap& best_matches, const GURL& origin) const { - ManagePasswordsUIController* manage_passwords_ui_controller = - ManagePasswordsUIController::FromWebContents(web_contents()); + PasswordsClientUIDelegate* manage_passwords_ui_controller = + PasswordsClientUIDelegateFromWebContents(web_contents()); if (manage_passwords_ui_controller && IsTheHotNewBubbleUIEnabled()) manage_passwords_ui_controller->OnPasswordAutofilled(best_matches, origin); }
diff --git a/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc b/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc index e1bbe5e..4a2a8c1 100644 --- a/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc +++ b/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc
@@ -11,11 +11,11 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "components/password_manager/core/browser/password_manager_constants.h" #include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" @@ -24,11 +24,11 @@ void GeneratedPasswordSavedInfoBarDelegateAndroid::OnInlineLinkClicked() { if (smart_lock_branding_enabled_) { - InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL( - content::OpenURLParams( - GURL(chrome::kPasswordManagerAccountDashboardURL), - content::Referrer(), NEW_FOREGROUND_TAB, - ui::PAGE_TRANSITION_LINK, false)); + InfoBarService::WebContentsFromInfoBar(infobar()) + ->OpenURL(content::OpenURLParams( + GURL(password_manager::kPasswordManagerAccountDashboardURL), + content::Referrer(), NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, + false)); } else { chrome::android::ChromeApplication::ShowPasswordSettings(); } @@ -49,7 +49,7 @@ int confirmation_id = IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT_INFOBAR; if (smart_lock_branding_enabled_) { std::string management_hostname = - GURL(chrome::kPasswordManagerAccountDashboardURL).host(); + GURL(password_manager::kPasswordManagerAccountDashboardURL).host(); link = base::UTF8ToUTF16(management_hostname); confirmation_id = IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_SMART_LOCK_TEXT_INFOBAR;
diff --git a/chrome/browser/password_manager/password_manager_infobar_delegate.cc b/chrome/browser/password_manager/password_manager_infobar_delegate.cc index c19dabb8..c7f608d6 100644 --- a/chrome/browser/password_manager/password_manager_infobar_delegate.cc +++ b/chrome/browser/password_manager/password_manager_infobar_delegate.cc
@@ -5,12 +5,10 @@ #include "chrome/browser/password_manager/password_manager_infobar_delegate.h" #include "chrome/browser/infobars/infobar_service.h" -#include "chrome/grit/chromium_strings.h" -#include "chrome/grit/generated_resources.h" #include "components/infobars/core/infobar.h" +#include "components/password_manager/core/browser/password_manager_constants.h" #include "content/public/browser/web_contents.h" #include "grit/theme_resources.h" -#include "ui/base/l10n/l10n_util.h" PasswordManagerInfoBarDelegate::~PasswordManagerInfoBarDelegate() {} @@ -41,7 +39,7 @@ } GURL PasswordManagerInfoBarDelegate::GetLinkURL() const { - return GURL(l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK_PAGE)); + return GURL(password_manager::kPasswordManagerAccountDashboardURL); } bool PasswordManagerInfoBarDelegate::LinkClicked(
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 44cc7bdd..a6129bb2f 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -542,7 +542,6 @@ RunTestsInFile("material_elements_test.js", "test.pdf"); } -// TODO(tsergeant): Verify that flake is fixed. http://crbug.com/550015 IN_PROC_BROWSER_TEST_F(MaterialPDFExtensionTest, ToolbarManager) { RunTestsInFile("toolbar_manager_test.js", "test.pdf"); }
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index e28497c..875bed1 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -107,6 +107,7 @@ #include "components/search/search.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" +#include "components/security_interstitials/core/controller_client.h" #include "components/ssl_config/ssl_config_prefs.h" #include "components/translate/core/browser/language_state.h" #include "components/translate/core/browser/translate_infobar_delegate.h" @@ -3745,11 +3746,11 @@ // by sending false if it's not present. " window.domAutomationController.send(%d);" "}", - SecurityInterstitialPage::CMD_TEXT_FOUND, - SecurityInterstitialPage::CMD_TEXT_NOT_FOUND, - SecurityInterstitialPage::CMD_ERROR); + security_interstitials::CMD_TEXT_FOUND, + security_interstitials::CMD_TEXT_NOT_FOUND, + security_interstitials::CMD_ERROR); EXPECT_TRUE(content::ExecuteScriptAndExtractInt(rvh, command, &result)); - EXPECT_EQ(SecurityInterstitialPage::CMD_TEXT_NOT_FOUND, result); + EXPECT_EQ(security_interstitials::CMD_TEXT_NOT_FOUND, result); } // Test that when SSL error overriding is allowed by policy (default), the @@ -3828,7 +3829,7 @@ SSLBlockingPage* ssl_delegate = static_cast<SSLBlockingPage*>(interstitial_delegate); ssl_delegate->CommandReceived( - base::IntToString(SecurityInterstitialPage::CMD_PROCEED)); + base::IntToString(security_interstitials::CMD_PROCEED)); EXPECT_TRUE(interstitial); EXPECT_TRUE(browser() ->tab_strip_model()
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 6f1c2a1..6a68c08b 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -476,8 +476,7 @@ main_context->set_host_resolver( io_thread_globals->host_resolver.get()); - main_context->set_cert_transparency_verifier( - io_thread_globals->cert_transparency_verifier.get()); + main_context->set_http_auth_handler_factory( io_thread_globals->http_auth_handler_factory.get());
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index d3fc549..595057a 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -68,6 +68,7 @@ #include "net/base/keygen_handler.h" #include "net/base/network_quality_estimator.h" #include "net/cert/cert_verifier.h" +#include "net/cert/multi_log_ct_verifier.h" #include "net/cookies/canonical_cookie.h" #include "net/http/http_network_session.h" #include "net/http/http_transaction_factory.h" @@ -1138,6 +1139,12 @@ profile_params_->new_tab_page_interceptor.release()); } + scoped_ptr<net::MultiLogCTVerifier> ct_verifier( + new net::MultiLogCTVerifier()); + ct_verifier->AddLogs(io_thread_globals->ct_logs); + main_request_context_->set_cert_transparency_verifier(ct_verifier.get()); + cert_transparency_verifier_ = ct_verifier.Pass(); + InitializeInternal( network_delegate.Pass(), profile_params_.get(), protocol_handlers, request_interceptors.Pass());
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 34a014e..eb27c12 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -25,6 +25,7 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_context.h" +#include "net/cert/ct_verifier.h" #include "net/cookies/cookie_monster.h" #include "net/http/http_cache.h" #include "net/http/http_network_session.h" @@ -542,6 +543,7 @@ mutable scoped_ptr<net::ProxyService> proxy_service_; mutable scoped_ptr<net::TransportSecurityState> transport_security_state_; + mutable scoped_ptr<net::CTVerifier> cert_transparency_verifier_; mutable scoped_ptr<net::HttpServerProperties> http_server_properties_; #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index e2a1693..87e9eb3 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -318,6 +318,7 @@ ":chromevox_unitjs_tests", "//base", "//base:i18n", + "//base/allocator", "//base/test:test_support", "//chrome:browser_tests_pak", "//chrome:packed_extra_resources",
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi b/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi index 7fb72f1..73a5ea7 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi +++ b/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi
@@ -122,6 +122,11 @@ '<(DEPTH)/native_client/src/trusted/service_runtime/linux/nacl_bootstrap.gyp:nacl_helper_bootstrap', ], }], + ['OS=="win" and win_use_allocator_shim==1', { + 'dependencies': [ + '<(DEPTH)/base/allocator/allocator.gyp:allocator', + ], + }], ], 'defines': [ 'HAS_OUT_OF_PROC_TEST_RUNNER',
diff --git a/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js b/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js index eaa2d1b..630c365 100644 --- a/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js +++ b/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js
@@ -435,6 +435,19 @@ /** + * @param {number} start + * @param {number} end + * @return { + * ({top: number, left: number, height: number, width: number})|undefined} + */ +chrome.automation.AutomationNode.prototype.boundsForRange = + function(start, end) {}; + + +chrome.automation.AutomationNode.prototype.makeVisible = function() {}; + + +/** * @param {chrome.automation.EventType} eventType * @param {function(!chrome.automation.AutomationEvent) : void} callback * @param {boolean} capture
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index a9206ac..007b5bd6 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -151,6 +151,9 @@ return; this.currentRange_ = value; + + if (this.currentRange_) + this.currentRange_.start.node.makeVisible(); }, /** @@ -328,8 +331,8 @@ .onSpeechEnd(function() { continueReading(prevRange); }) .go(); prevRange = this.currentRange_; - this.currentRange_ = - this.currentRange_.move(cursors.Unit.NODE, Dir.FORWARD); + this.currentRange = + this.currentRange.move(cursors.Unit.NODE, Dir.FORWARD); if (!this.currentRange_ || this.currentRange_.equals(prevRange)) global.isReadingContinuously = false; @@ -405,7 +408,7 @@ actionNode.focus(); var prevRange = this.currentRange_; - this.currentRange_ = current; + this.currentRange = current; new Output().withSpeechAndBraille( this.currentRange_, prevRange, Output.EventType.NAVIGATE)
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/base_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/base_automation_handler.js index 02c6aee..7b25b2ac 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/base_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/base_automation_handler.js
@@ -35,6 +35,7 @@ loadComplete: this.onLoadComplete, menuStart: this.onEventDefault, menuEnd: this.onEventDefault, + scrollPositionChanged: this.onScrollPositionChanged, textChanged: this.onTextOrTextSelectionChanged, textSelectionChanged: this.onTextOrTextSelectionChanged, valueChanged: this.onValueChanged @@ -114,11 +115,20 @@ * @param {Object} evt */ onLoadComplete: function(evt) {}, + + /** + * @param {Object} evt + */ onEventDefault: function(evt) {}, /** * @param {Object} evt */ + onScrollPositionChanged: function(evt) {}, + + /** + * @param {Object} evt + */ onTextOrTextSelectionChanged: function(evt) {}, /**
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index 182bbd4..c16454506 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -247,6 +247,16 @@ }, /** + * Handle updating the active indicator when the document scrolls. + * @override + */ + onScrollPositionChanged: function(evt) { + var currentRange = global.backgroundObj.currentRange; + if (currentRange) + new Output().withLocation(currentRange, null, evt.type).go(); + }, + + /** * Create an editable text handler for the given node if needed. * @param {Object} node */
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js index 15a556e..d5f3e83 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -63,9 +63,9 @@ /** * Current global options. - * @type {{speech: boolean, braille: boolean, location: boolean}} + * @type {{speech: boolean, braille: boolean}} */ - this.formatOptions_ = {speech: true, braille: false, location: true}; + this.formatOptions_ = {speech: true, braille: false}; /** * Speech properties to apply to the entire output. @@ -618,7 +618,7 @@ * @return {!Output} */ withSpeech: function(range, prevRange, type) { - this.formatOptions_ = {speech: true, braille: false, location: true}; + this.formatOptions_ = {speech: true, braille: false}; this.render_(range, prevRange, type, this.speechBuffer_); return this; }, @@ -631,12 +631,25 @@ * @return {!Output} */ withBraille: function(range, prevRange, type) { - this.formatOptions_ = {speech: false, braille: true, location: false}; + this.formatOptions_ = {speech: false, braille: true}; this.render_(range, prevRange, type, this.brailleBuffer_); return this; }, /** + * Specify ranges for location. + * @param {!cursors.Range} range + * @param {cursors.Range} prevRange + * @param {chrome.automation.EventType|Output.EventType} type + * @return {!Output} + */ + withLocation: function(range, prevRange, type) { + this.formatOptions_ = {speech: false, braille: false}; + this.render_(range, prevRange, type, this.speechBuffer_); + return this; + }, + + /** * Specify the same ranges for speech and braille. * @param {!cursors.Range} range * @param {cursors.Range} prevRange @@ -666,10 +679,10 @@ * @return {!Output} */ format: function(formatStr) { - this.formatOptions_ = {speech: true, braille: false, location: true}; + this.formatOptions_ = {speech: true, braille: false}; this.format_(null, formatStr, this.speechBuffer_); - this.formatOptions_ = {speech: false, braille: true, location: false}; + this.formatOptions_ = {speech: false, braille: true}; this.format_(null, formatStr, this.brailleBuffer_); return this; @@ -1054,8 +1067,7 @@ var buff = []; this.ancestry_(node, prevNode, type, buff); this.node_(node, prevNode, type, buff); - if (this.formatOptions_.location) - this.locations_.push(node.location); + this.locations_.push(node.location); return buff; }.bind(this); @@ -1183,6 +1195,8 @@ endIndex++; this.append_( buff, range.start.getText().substring(startIndex, endIndex)); + this.locations_.push( + range.start.node.boundsForRange(startIndex, endIndex)); }, /**
diff --git a/chrome/browser/resources/md_downloads/crisper.js b/chrome/browser/resources/md_downloads/crisper.js index 49ea6974..da445238 100644 --- a/chrome/browser/resources/md_downloads/crisper.js +++ b/chrome/browser/resources/md_downloads/crisper.js
@@ -1465,12 +1465,15 @@ * @return {T} A non-null |condition|. */ function assert(condition, opt_message) { - 'use strict'; if (!condition) { - var msg = 'Assertion failed'; + var message = 'Assertion failed'; if (opt_message) - msg = msg + ': ' + opt_message; - throw new Error(msg); + message = message + ': ' + opt_message; + var error = new Error(message); + var global = function() { return this; }(); + if (global.traceAssertionsForTesting) + console.warn(error.stack); + throw error; } return condition; } @@ -1497,7 +1500,7 @@ * @param {string=} opt_message A message to show when this is hit. */ function assertNotReached(opt_message) { - throw new Error(opt_message || 'Unreachable code hit'); + assert(false, opt_message || 'Unreachable code hit'); } /** @@ -1508,10 +1511,8 @@ * @template T */ function assertInstanceof(value, type, opt_message) { - if (!(value instanceof type)) { - throw new Error(opt_message || - value + ' is not a[n] ' + (type.name || typeof type)); - } + assert(value instanceof type, + opt_message || value + ' is not a[n] ' + (type.name || typeof type)); return value; }; // Copyright 2015 The Chromium Authors. All rights reserved. @@ -1804,10 +1805,11 @@ window.Polymer = { Settings: function () { var user = window.Polymer || {}; -location.search.slice(1).split('&').forEach(function (o) { +var parts = location.search.slice(1).split('&'); +for (var i = 0, o; i < parts.length && (o = parts[i]); i++) { 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; @@ -1894,15 +1896,53 @@ }, _makeReady: function () { this._ready = true; -this._callbacks.forEach(function (cb) { -cb(); -}); +for (var i = 0; i < this._callbacks.length; i++) { +this._callbacks[i](); +} this._callbacks = []; }, _catchFirstRender: function () { requestAnimationFrame(function () { Polymer.RenderStatus._makeReady(); }); +}, +_afterNextRenderQueue: [], +_waitingNextRender: false, +afterNextRender: function (element, fn, args) { +this._watchNextRender(); +this._afterNextRenderQueue.push([ +element, +fn, +args +]); +}, +_watchNextRender: function () { +if (!this._waitingNextRender) { +this._waitingNextRender = true; +var fn = function () { +Polymer.RenderStatus._flushNextRender(); +}; +if (!this._ready) { +this.whenReady(fn); +} else { +requestAnimationFrame(fn); +} +} +}, +_flushNextRender: function () { +var self = this; +setTimeout(function () { +self._flushRenderCallbacks(self._afterNextRenderQueue); +self._afterNextRenderQueue = []; +self._waitingNextRender = false; +}); +}, +_flushRenderCallbacks: function (callbacks) { +for (var i = 0, h; i < callbacks.length; i++) { +h = callbacks[i]; +h[1].apply(h[0], h[2] || Polymer.nar); +} +; } }; if (window.HTMLImports) { @@ -1932,27 +1972,33 @@ this._initFeatures(); }, attachedCallback: function () { +var self = this; Polymer.RenderStatus.whenReady(function () { -this.isAttached = true; -this._doBehavior('attached'); -}.bind(this)); +self.isAttached = true; +self._doBehavior('attached'); +}); }, detachedCallback: function () { this.isAttached = false; this._doBehavior('detached'); }, -attributeChangedCallback: function (name) { +attributeChangedCallback: function (name, oldValue, newValue) { this._attributeChangedImpl(name); -this._doBehavior('attributeChanged', arguments); +this._doBehavior('attributeChanged', [ +name, +oldValue, +newValue +]); }, _attributeChangedImpl: function (name) { this._setAttributeToProperty(this, name); }, extend: function (prototype, api) { if (prototype && api) { -Object.getOwnPropertyNames(api).forEach(function (n) { +var n$ = Object.getOwnPropertyNames(api); +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { this.copyOwnProperty(n, api, prototype); -}, this); +} } return prototype || api; }, @@ -2030,7 +2076,7 @@ if (id) { var m = findModule(id); if (!m) { -forceDocumentUpgrade(); +forceDomModulesUpgrade(); m = findModule(id); } if (m && selector) { @@ -2042,12 +2088,17 @@ }); var cePolyfill = window.CustomElements && !CustomElements.useNative; document.registerElement('dom-module', DomModule); -function forceDocumentUpgrade() { +function forceDomModulesUpgrade() { if (cePolyfill) { var script = document._currentScript || document.currentScript; -var doc = script && script.ownerDocument; -if (doc) { -CustomElements.upgradeAll(doc); +var doc = script && script.ownerDocument || document; +var modules = doc.querySelectorAll('dom-module'); +for (var i = modules.length - 1, m; i >= 0 && (m = modules[i]); i--) { +if (m.__upgraded__) { +return; +} else { +CustomElements.upgrade(m); +} } } } @@ -2082,7 +2133,8 @@ }, _flattenBehaviorsList: function (behaviors) { var flat = []; -behaviors.forEach(function (b) { +for (var i = 0; i < behaviors.length; i++) { +var b = behaviors[i]; if (b instanceof Array) { flat = flat.concat(this._flattenBehaviorsList(b)); } else if (b) { @@ -2090,31 +2142,16 @@ } else { this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import')); } -}, this); +} return flat; }, _mixinBehavior: function (b) { -Object.getOwnPropertyNames(b).forEach(function (n) { -switch (n) { -case 'hostAttributes': -case 'registered': -case 'properties': -case 'observers': -case 'listeners': -case 'created': -case 'attached': -case 'detached': -case 'attributeChanged': -case 'configure': -case 'ready': -break; -default: -if (!this.hasOwnProperty(n)) { +var n$ = Object.getOwnPropertyNames(b); +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { +if (!Polymer.Base._behaviorProperties[n] && !this.hasOwnProperty(n)) { this.copyOwnProperty(n, b, this); } -break; } -}, this); }, _prepBehaviors: function () { this._prepFlattenedBehaviors(this.behaviors); @@ -2126,9 +2163,9 @@ this._prepBehavior(this); }, _doBehavior: function (name, args) { -this.behaviors.forEach(function (b) { -this._invokeBehavior(b, name, args); -}, this); +for (var i = 0; i < this.behaviors.length; i++) { +this._invokeBehavior(this.behaviors[i], name, args); +} this._invokeBehavior(this, name, args); }, _invokeBehavior: function (b, name, args) { @@ -2138,12 +2175,24 @@ } }, _marshalBehaviors: function () { -this.behaviors.forEach(function (b) { -this._marshalBehavior(b); -}, this); +for (var i = 0; i < this.behaviors.length; i++) { +this._marshalBehavior(this.behaviors[i]); +} this._marshalBehavior(this); } }); +Polymer.Base._behaviorProperties = { +hostAttributes: true, +registered: true, +properties: true, +observers: true, +listeners: true, +created: true, +attached: true, +detached: true, +attributeChanged: true, +ready: true +}; Polymer.Base._addFeature({ _getExtendedPrototype: function (tag) { return this._getExtendedNativePrototype(tag); @@ -2195,9 +2244,13 @@ 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); +for (var i = 0; i < this.behaviors.length; i++) { +info = this._getPropertyInfo(property, this.behaviors[i].properties); +if (info) { +return info; +} +} +; } return info || Polymer.nob; }, @@ -2210,6 +2263,40 @@ p.defined = true; } return p; +}, +_prepPropertyInfo: function () { +this._propertyInfo = {}; +for (var i = 0, p; i < this.behaviors.length; i++) { +this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties); +} +this._addPropertyInfo(this._propertyInfo, this.properties); +this._addPropertyInfo(this._propertyInfo, this._propertyEffects); +}, +_addPropertyInfo: function (target, source) { +if (source) { +var t, s; +for (var i in source) { +t = target[i]; +s = source[i]; +if (i[0] === '_' && !s.readOnly) { +continue; +} +if (!target[i]) { +target[i] = { +type: typeof s === 'function' ? s : s.type, +readOnly: s.readOnly, +attribute: Polymer.CaseMap.camelToDashCase(i) +}; +} else { +if (!t.type) { +t.type = s.type; +} +if (!t.readOnly) { +t.readOnly = s.readOnly; +} +} +} +} } }); Polymer.CaseMap = { @@ -2237,21 +2324,24 @@ } }; Polymer.Base._addFeature({ -_prepAttributes: function () { -this._aggregatedAttributes = {}; -}, _addHostAttributes: function (attributes) { +if (!this._aggregatedAttributes) { +this._aggregatedAttributes = {}; +} if (attributes) { this.mixin(this._aggregatedAttributes, attributes); } }, _marshalHostAttributes: function () { +if (this._aggregatedAttributes) { this._applyAttributes(this, this._aggregatedAttributes); +} }, _applyAttributes: function (node, attr$) { for (var n in attr$) { if (!this.hasAttribute(n) && n !== 'class') { -this.serializeValueToAttribute(attr$[n], n, this); +var v = attr$[n]; +this.serializeValueToAttribute(v, n, this); } } }, @@ -2259,29 +2349,40 @@ this._takeAttributesToModel(this); }, _takeAttributesToModel: function (model) { -for (var i = 0, l = this.attributes.length; i < l; i++) { -this._setAttributeToProperty(model, this.attributes[i].name); +if (this.hasAttributes()) { +for (var i in this._propertyInfo) { +var info = this._propertyInfo[i]; +if (this.hasAttribute(info.attribute)) { +this._setAttributeToProperty(model, info.attribute, i, info); +} +} } }, -_setAttributeToProperty: function (model, attrName) { +_setAttributeToProperty: function (model, attribute, property, info) { if (!this._serializing) { -var propName = Polymer.CaseMap.dashToCamelCase(attrName); -var info = this.getPropertyInfo(propName); -if (info.defined || this._propertyEffects && this._propertyEffects[propName]) { -var val = this.getAttribute(attrName); -model[propName] = this.deserialize(val, info.type); +var property = property || Polymer.CaseMap.dashToCamelCase(attribute); +info = info || this._propertyInfo && this._propertyInfo[property]; +if (info && !info.readOnly) { +var v = this.getAttribute(attribute); +model[property] = this.deserialize(v, info.type); } } }, _serializing: false, -reflectPropertyToAttribute: function (name) { +reflectPropertyToAttribute: function (property, attribute, value) { this._serializing = true; -this.serializeValueToAttribute(this[name], Polymer.CaseMap.camelToDashCase(name)); +value = value === undefined ? this[property] : value; +this.serializeValueToAttribute(value, attribute || Polymer.CaseMap.camelToDashCase(property)); this._serializing = false; }, serializeValueToAttribute: function (value, attribute, node) { var str = this.serialize(value); -(node || this)[str === undefined ? 'removeAttribute' : 'setAttribute'](attribute, str); +node = node || this; +if (str === undefined) { +node.removeAttribute(attribute); +} else { +node.setAttribute(attribute, str); +} }, deserialize: function (value, type) { switch (type) { @@ -2357,13 +2458,13 @@ } } }); -Polymer.version = '1.1.5'; +Polymer.version = '1.2.3'; Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); -this._prepAttributes(); this._prepBehaviors(); this._prepConstructor(); +this._prepPropertyInfo(); }, _prepBehavior: function (b) { this._addHostAttributes(b.hostAttributes); @@ -2378,13 +2479,14 @@ }); Polymer.Base._addFeature({ _prepTemplate: function () { -this._template = this._template || Polymer.DomModule.import(this.is, 'template'); +if (this._template === undefined) { +this._template = Polymer.DomModule.import(this.is, 'template'); +} if (this._template && this._template.hasAttribute('is')) { this._warn(this._logf('_prepTemplate', 'top-level Polymer template ' + 'must not be a type-extension, found', this._template, 'Move inside simple <template>.')); } -if (this._template && !this._template.content && HTMLTemplateElement.bootstrap) { +if (this._template && !this._template.content && window.HTMLTemplateElement && HTMLTemplateElement.decorate) { HTMLTemplateElement.decorate(this._template); -HTMLTemplateElement.bootstrap(this._template.content); } }, _stampTemplate: function () { @@ -2403,20 +2505,19 @@ _hostStack: [], ready: function () { }, -_pushHost: function (host) { +_registerHost: function (host) { this.dataHost = host = host || Polymer.Base._hostStack[Polymer.Base._hostStack.length - 1]; if (host && host._clients) { host._clients.push(this); } -this._beginHost(); }, -_beginHost: function () { +_beginHosting: function () { Polymer.Base._hostStack.push(this); if (!this._clients) { this._clients = []; } }, -_popHost: function () { +_endHosting: function () { Polymer.Base._hostStack.pop(); }, _tryReady: function () { @@ -2429,20 +2530,24 @@ }, _ready: function () { this._beforeClientsReady(); +if (this._template) { this._setupRoot(); this._readyClients(); +} +this._clientsReadied = true; +this._clients = null; this._afterClientsReady(); this._readySelf(); }, _readyClients: function () { this._beginDistribute(); var c$ = this._clients; +if (c$) { for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { c._ready(); } +} this._finishDistribute(); -this._clientsReadied = true; -this._clients = null; }, _readySelf: function () { this._doBehavior('ready'); @@ -2638,61 +2743,6 @@ }; 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]; -} -} -}, -get path() { -if (!this.event._path) { -var path = []; -var o = this.rootTarget; -while (o) { -path.push(o); -o = Polymer.dom(o).parentNode || o.host; -} -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.domInnerHTML = function () { var escapeAttrRegExp = /[&\u00A0"]/g; var escapeDataRegExp = /[&\u00A0<>]/g; @@ -2800,24 +2850,31 @@ var nativeAppendChild = Element.prototype.appendChild; var nativeCloneNode = Element.prototype.cloneNode; var nativeImportNode = Document.prototype.importNode; +var needsToWrap = Settings.hasShadow && !Settings.nativeShadow; +var wrap = window.wrap ? window.wrap : function (node) { +return node; +}; var DomApi = function (node) { -this.node = node; +this.node = needsToWrap ? wrap(node) : node; if (this.patch) { this.patch(); } }; -if (window.wrap && Settings.useShadow && !Settings.useNativeShadow) { -DomApi = function (node) { -this.node = wrap(node); -if (this.patch) { -this.patch(); -} -}; -} DomApi.prototype = { flush: function () { Polymer.dom.flush(); }, +deepContains: function (node) { +if (this.node.contains(node)) { +return true; +} +var n = node; +var wrappedDocument = wrap(document); +while (n && n !== wrappedDocument && n !== this.node) { +n = Polymer.dom(n).parentNode || n.host; +} +return n === this.node; +}, _lazyDistribute: function (host) { if (host.shadyRoot && host.shadyRoot._distributionClean) { host.shadyRoot._distributionClean = false; @@ -2831,7 +2888,7 @@ return this._addNode(node, ref_node); }, _addNode: function (node, ref_node) { -this._removeNodeFromHost(node, true); +this._removeNodeFromParent(node); var addedInsertionPoint; var root = this.getOwnerRoot(); if (root) { @@ -2863,6 +2920,7 @@ if (addedInsertionPoint) { this._updateInsertionPoints(root.host); } +this.notifyObserver(); return node; }, removeChild: function (node) { @@ -2877,6 +2935,7 @@ nativeRemoveChild.call(container, node); } } +this.notifyObserver(); return node; }, replaceChild: function (node, ref_node) { @@ -2969,6 +3028,13 @@ _parentNeedsDistribution: function (parent) { return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot); }, +_removeNodeFromParent: function (node) { +var parent = node._lightParent || node.parentNode; +if (parent && hasDomApi(parent)) { +factory(parent).notifyObserver(); +} +this._removeNodeFromHost(node, true); +}, _removeNodeFromHost: function (node, ensureComposedRemoval) { var hostNeedsDist; var root; @@ -2980,7 +3046,7 @@ root.host._elementRemove(node); hostNeedsDist = this._removeDistributedChildren(root, node); } -this._removeLogicalInfo(node, node._lightParent); +this._removeLogicalInfo(node, parent); } this._removeOwnerShadyRoot(node); if (root && hostNeedsDist) { @@ -3028,7 +3094,7 @@ var children = factory(container).childNodes; index = index === undefined ? children.length : index; if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { -var c$ = Array.prototype.slice.call(node.childNodes); +var c$ = arrayCopyChildNodes(node); for (var i = 0, n; i < c$.length && (n = c$[i]); i++) { children.splice(index++, 0, n); n._lightParent = container; @@ -3099,24 +3165,29 @@ return this.node._distributedNodes || []; }, queryDistributedElements: function (selector) { -var c$ = this.childNodes; +var c$ = this.getEffectiveChildNodes(); 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); +if (c.nodeType === Node.ELEMENT_NODE && matchesSelector.call(c, selector)) { +list.push(c); } } 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); +getEffectiveChildNodes: function () { +var list = []; +var c$ = this.childNodes; +for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { +if (c.localName === CONTENT) { +var d$ = factory(c).getDistributedNodes(); +for (var j = 0; j < d$.length; j++) { +list.push(d$[j]); +} +} else { +list.push(c); } } -return results; +return list; }, _clear: function () { while (this.childNodes.length) { @@ -3160,36 +3231,24 @@ } } return n; +}, +observeNodes: function (callback) { +if (callback) { +if (!this.observer) { +this.observer = this.node.localName === CONTENT ? new DomApi.DistributedNodesObserver(this) : new DomApi.EffectiveNodesObserver(this); } -}; -Object.defineProperty(DomApi.prototype, 'classList', { -get: function () { -if (!this._classList) { -this._classList = new DomApi.ClassList(this); +return this.observer.addListener(callback); } -return this._classList; }, -configurable: true -}); -DomApi.ClassList = function (host) { -this.domApi = host; -this.node = host.node; -}; -DomApi.ClassList.prototype = { -add: function () { -this.node.classList.add.apply(this.node.classList, arguments); -this.domApi._distributeParent(); +unobserveNodes: function (handle) { +if (this.observer) { +this.observer.removeListener(handle); +} }, -remove: function () { -this.node.classList.remove.apply(this.node.classList, arguments); -this.domApi._distributeParent(); -}, -toggle: function () { -this.node.classList.toggle.apply(this.node.classList, arguments); -this.domApi._distributeParent(); -}, -contains: function () { -return this.node.classList.contains.apply(this.node.classList, arguments); +notifyObserver: function () { +if (this.observer) { +this.observer.notify(); +} } }; if (!Settings.useShadow) { @@ -3197,7 +3256,7 @@ childNodes: { get: function () { var c$ = getLightChildren(this.node); -return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$); +return Array.isArray(c$) ? c$ : arrayCopyChildNodes(this.node); }, configurable: true }, @@ -3320,7 +3379,7 @@ this._clear(); var d = document.createElement('div'); d.innerHTML = text; -var c$ = Array.prototype.slice.call(d.childNodes); +var c$ = arrayCopyChildNodes(d); for (var i = 0; i < c$.length; i++) { this.appendChild(c$[i]); } @@ -3333,20 +3392,25 @@ return getInnerHTML(this.node, true); }; } else { -var forwardMethods = [ +var forwardMethods = function (m$) { +for (var i = 0; i < m$.length; i++) { +forwardMethod(m$[i]); +} +}; +var forwardMethod = function (method) { +DomApi.prototype[method] = function () { +return this.node[method].apply(this.node, arguments); +}; +}; +forwardMethods([ 'cloneNode', 'appendChild', 'insertBefore', 'removeChild', 'replaceChild' -]; -forwardMethods.forEach(function (name) { -DomApi.prototype[name] = function () { -return this.node[name].apply(this.node, arguments); -}; -}); +]); DomApi.prototype.querySelectorAll = function (selector) { -return Array.prototype.slice.call(this.node.querySelectorAll(selector)); +return arrayCopy(this.node.querySelectorAll(selector)); }; DomApi.prototype.getOwnerRoot = function () { var n = this.node; @@ -3363,24 +3427,24 @@ }; DomApi.prototype.getDestinationInsertionPoints = function () { var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInsertionPoints(); -return n$ ? Array.prototype.slice.call(n$) : []; +return n$ ? arrayCopy(n$) : []; }; DomApi.prototype.getDistributedNodes = function () { var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes(); -return n$ ? Array.prototype.slice.call(n$) : []; +return n$ ? arrayCopy(n$) : []; }; DomApi.prototype._distributeParent = function () { }; Object.defineProperties(DomApi.prototype, { childNodes: { get: function () { -return Array.prototype.slice.call(this.node.childNodes); +return arrayCopyChildNodes(this.node); }, configurable: true }, children: { get: function () { -return Array.prototype.slice.call(this.node.children); +return arrayCopyChildren(this.node); }, configurable: true }, @@ -3403,7 +3467,20 @@ configurable: true } }); -var forwardProperties = [ +var forwardProperties = function (f$) { +for (var i = 0; i < f$.length; i++) { +forwardProperty(f$[i]); +} +}; +var forwardProperty = function (name) { +Object.defineProperty(DomApi.prototype, name, { +get: function () { +return this.node[name]; +}, +configurable: true +}); +}; +forwardProperties([ 'parentNode', 'firstChild', 'lastChild', @@ -3413,24 +3490,21 @@ 'lastElementChild', 'nextElementSibling', 'previousElementSibling' -]; -forwardProperties.forEach(function (name) { -Object.defineProperty(DomApi.prototype, name, { -get: function () { -return this.node[name]; -}, -configurable: true -}); -}); +]); } var CONTENT = 'content'; -var factory = function (node, patch) { +function factory(node, patch) { node = node || document; if (!node.__domApi) { node.__domApi = new DomApi(node, patch); } return node.__domApi; -}; +} +; +function hasDomApi(node) { +return Boolean(node.__domApi); +} +; Polymer.dom = function (obj, patch) { if (obj instanceof Event) { return Polymer.EventApi.factory(obj); @@ -3438,50 +3512,13 @@ return factory(obj, patch); } }; -Polymer.Base.extend(Polymer.dom, { -_flushGuard: 0, -_FLUSH_MAX: 100, -_needsTakeRecords: !Polymer.Settings.useNativeCustomElements, -_debouncers: [], -_finishDebouncer: null, -flush: function () { -for (var i = 0; i < this._debouncers.length; i++) { -this._debouncers[i].complete(); -} -if (this._finishDebouncer) { -this._finishDebouncer.complete(); -} -this._flushPolyfills(); -if (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) { -this._flushGuard++; -this.flush(); -} else { -if (this._flushGuard >= this._FLUSH_MAX) { -console.warn('Polymer.dom.flush aborted. Flush may not be complete.'); -} -this._flushGuard = 0; -} -}, -_flushPolyfills: function () { -if (this._needsTakeRecords) { -CustomElements.takeRecords(); -} -}, -addDebouncer: function (debouncer) { -this._debouncers.push(debouncer); -this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlush); -}, -_finishFlush: function () { -Polymer.dom._debouncers = []; -} -}); function getLightChildren(node) { var children = node._lightChildren; return children ? children : node.childNodes; } function getComposedChildren(node) { if (!node._composedChildren) { -node._composedChildren = Array.prototype.slice.call(node.childNodes); +node._composedChildren = arrayCopyChildNodes(node); } return node._composedChildren; } @@ -3517,13 +3554,35 @@ } function saveLightChildrenIfNeeded(node) { if (!node._lightChildren) { -var c$ = Array.prototype.slice.call(node.childNodes); +var c$ = arrayCopyChildNodes(node); for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) { child._lightParent = child._lightParent || node; } node._lightChildren = c$; } } +function arrayCopyChildNodes(parent) { +var copy = [], i = 0; +for (var n = parent.firstChild; n; n = n.nextSibling) { +copy[i++] = n; +} +return copy; +} +function arrayCopyChildren(parent) { +var copy = [], i = 0; +for (var n = parent.firstElementChild; n; n = n.nextElementSibling) { +copy[i++] = n; +} +return copy; +} +function arrayCopy(a$) { +var l = a$.length; +var copy = new Array(l); +for (var i = 0; i < l; i++) { +copy[i] = a$[i]; +} +return copy; +} function hasInsertionPoint(root) { return Boolean(root && root._insertionPoints.length); } @@ -3538,10 +3597,411 @@ matchesSelector: matchesSelector, hasInsertionPoint: hasInsertionPoint, ctor: DomApi, -factory: factory +factory: factory, +hasDomApi: hasDomApi, +arrayCopy: arrayCopy, +arrayCopyChildNodes: arrayCopyChildNodes, +arrayCopyChildren: arrayCopyChildren, +wrap: wrap }; }(); +Polymer.Base.extend(Polymer.dom, { +_flushGuard: 0, +_FLUSH_MAX: 100, +_needsTakeRecords: !Polymer.Settings.useNativeCustomElements, +_debouncers: [], +_staticFlushList: [], +_finishDebouncer: null, +flush: function () { +this._flushGuard = 0; +this._prepareFlush(); +while (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) { +for (var i = 0; i < this._debouncers.length; i++) { +this._debouncers[i].complete(); +} +if (this._finishDebouncer) { +this._finishDebouncer.complete(); +} +this._prepareFlush(); +this._flushGuard++; +} +if (this._flushGuard >= this._FLUSH_MAX) { +console.warn('Polymer.dom.flush aborted. Flush may not be complete.'); +} +}, +_prepareFlush: function () { +if (this._needsTakeRecords) { +CustomElements.takeRecords(); +} +for (var i = 0; i < this._staticFlushList.length; i++) { +this._staticFlushList[i](); +} +}, +addStaticFlush: function (fn) { +this._staticFlushList.push(fn); +}, +removeStaticFlush: function (fn) { +var i = this._staticFlushList.indexOf(fn); +if (i >= 0) { +this._staticFlushList.splice(i, 1); +} +}, +addDebouncer: function (debouncer) { +this._debouncers.push(debouncer); +this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlush); +}, +_finishFlush: function () { +Polymer.dom._debouncers = []; +} +}); +Polymer.EventApi = function () { +'use strict'; +var DomApi = Polymer.DomApi.ctor; +var Settings = Polymer.Settings; +DomApi.Event = function (event) { +this.event = event; +}; +if (Settings.useShadow) { +DomApi.Event.prototype = { +get rootTarget() { +return this.event.path[0]; +}, +get localTarget() { +return this.event.target; +}, +get path() { +return this.event.path; +} +}; +} else { +DomApi.Event.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]; +} +} +}, +get path() { +if (!this.event._path) { +var path = []; +var o = this.rootTarget; +while (o) { +path.push(o); +o = Polymer.dom(o).parentNode || o.host; +} +path.push(window); +this.event._path = path; +} +return this.event._path; +} +}; +} +var factory = function (event) { +if (!event.__eventApi) { +event.__eventApi = new DomApi.Event(event); +} +return event.__eventApi; +}; +return { factory: factory }; +}(); (function () { +'use strict'; +var DomApi = Polymer.DomApi.ctor; +Object.defineProperty(DomApi.prototype, 'classList', { +get: function () { +if (!this._classList) { +this._classList = new DomApi.ClassList(this); +} +return this._classList; +}, +configurable: true +}); +DomApi.ClassList = function (host) { +this.domApi = host; +this.node = host.node; +}; +DomApi.ClassList.prototype = { +add: function () { +this.node.classList.add.apply(this.node.classList, arguments); +this.domApi._distributeParent(); +}, +remove: function () { +this.node.classList.remove.apply(this.node.classList, arguments); +this.domApi._distributeParent(); +}, +toggle: function () { +this.node.classList.toggle.apply(this.node.classList, arguments); +this.domApi._distributeParent(); +}, +contains: function () { +return this.node.classList.contains.apply(this.node.classList, arguments); +} +}; +}()); +(function () { +'use strict'; +var DomApi = Polymer.DomApi.ctor; +var Settings = Polymer.Settings; +var hasDomApi = Polymer.DomApi.hasDomApi; +DomApi.EffectiveNodesObserver = function (domApi) { +this.domApi = domApi; +this.node = this.domApi.node; +this._listeners = []; +}; +DomApi.EffectiveNodesObserver.prototype = { +addListener: function (callback) { +if (!this._isSetup) { +this._setup(); +this._isSetup = true; +} +var listener = { +fn: callback, +_nodes: [] +}; +this._listeners.push(listener); +this._scheduleNotify(); +return listener; +}, +removeListener: function (handle) { +var i = this._listeners.indexOf(handle); +if (i >= 0) { +this._listeners.splice(i, 1); +handle._nodes = []; +} +if (!this._hasListeners()) { +this._cleanup(); +this._isSetup = false; +} +}, +_setup: function () { +this._observeContentElements(this.domApi.childNodes); +}, +_cleanup: function () { +this._unobserveContentElements(this.domApi.childNodes); +}, +_hasListeners: function () { +return Boolean(this._listeners.length); +}, +_scheduleNotify: function () { +if (this._debouncer) { +this._debouncer.stop(); +} +this._debouncer = Polymer.Debounce(this._debouncer, this._notify); +this._debouncer.context = this; +Polymer.dom.addDebouncer(this._debouncer); +}, +notify: function () { +if (this._hasListeners()) { +this._scheduleNotify(); +} +}, +_notify: function (mxns) { +this._beforeCallListeners(); +this._callListeners(); +}, +_beforeCallListeners: function () { +this._updateContentElements(); +}, +_updateContentElements: function () { +this._observeContentElements(this.domApi.childNodes); +}, +_observeContentElements: function (elements) { +for (var i = 0, n; i < elements.length && (n = elements[i]); i++) { +if (this._isContent(n)) { +n.__observeNodesMap = n.__observeNodesMap || new WeakMap(); +if (!n.__observeNodesMap.has(this)) { +n.__observeNodesMap.set(this, this._observeContent(n)); +} +} +} +}, +_observeContent: function (content) { +var self = this; +var h = Polymer.dom(content).observeNodes(function () { +self._scheduleNotify(); +}); +h._avoidChangeCalculation = true; +return h; +}, +_unobserveContentElements: function (elements) { +for (var i = 0, n, h; i < elements.length && (n = elements[i]); i++) { +if (this._isContent(n)) { +h = n.__observeNodesMap.get(this); +if (h) { +Polymer.dom(n).unobserveNodes(h); +n.__observeNodesMap.delete(this); +} +} +} +}, +_isContent: function (node) { +return node.localName === 'content'; +}, +_callListeners: function () { +var o$ = this._listeners; +var nodes = this._getEffectiveNodes(); +for (var i = 0, o; i < o$.length && (o = o$[i]); i++) { +var info = this._generateListenerInfo(o, nodes); +if (info || o._alwaysNotify) { +this._callListener(o, info); +} +} +}, +_getEffectiveNodes: function () { +return this.domApi.getEffectiveChildNodes(); +}, +_generateListenerInfo: function (listener, newNodes) { +if (listener._avoidChangeCalculation) { +return true; +} +var oldNodes = listener._nodes; +var info = { +target: this.node, +addedNodes: [], +removedNodes: [] +}; +var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes); +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { +for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) { +info.removedNodes.push(n); +} +} +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { +for (var j = s.index; j < s.index + s.addedCount; j++) { +info.addedNodes.push(newNodes[j]); +} +} +listener._nodes = newNodes; +if (info.addedNodes.length || info.removedNodes.length) { +return info; +} +}, +_callListener: function (listener, info) { +return listener.fn.call(this.node, info); +}, +enableShadowAttributeTracking: function () { +} +}; +if (Settings.useShadow) { +var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup; +var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup; +var beforeCallListeners = DomApi.EffectiveNodesObserver.prototype._beforeCallListeners; +Polymer.Base.extend(DomApi.EffectiveNodesObserver.prototype, { +_setup: function () { +if (!this._observer) { +var self = this; +this._mutationHandler = function (mxns) { +if (mxns && mxns.length) { +self._scheduleNotify(); +} +}; +this._observer = new MutationObserver(this._mutationHandler); +this._boundFlush = function () { +self._flush(); +}; +Polymer.dom.addStaticFlush(this._boundFlush); +this._observer.observe(this.node, { childList: true }); +} +baseSetup.call(this); +}, +_cleanup: function () { +this._observer.disconnect(); +this._observer = null; +this._mutationHandler = null; +Polymer.dom.removeStaticFlush(this._boundFlush); +baseCleanup.call(this); +}, +_flush: function () { +if (this._observer) { +this._mutationHandler(this._observer.takeRecords()); +} +}, +enableShadowAttributeTracking: function () { +if (this._observer) { +this._makeContentListenersAlwaysNotify(); +this._observer.disconnect(); +this._observer.observe(this.node, { +childList: true, +attributes: true, +subtree: true +}); +var root = this.domApi.getOwnerRoot(); +var host = root && root.host; +if (host && Polymer.dom(host).observer) { +Polymer.dom(host).observer.enableShadowAttributeTracking(); +} +} +}, +_makeContentListenersAlwaysNotify: function () { +for (var i = 0, h; i < this._listeners.length; i++) { +h = this._listeners[i]; +h._alwaysNotify = h._isContentListener; +} +} +}); +} +}()); +(function () { +'use strict'; +var DomApi = Polymer.DomApi.ctor; +var Settings = Polymer.Settings; +DomApi.DistributedNodesObserver = function (domApi) { +DomApi.EffectiveNodesObserver.call(this, domApi); +}; +DomApi.DistributedNodesObserver.prototype = Object.create(DomApi.EffectiveNodesObserver.prototype); +Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, { +_setup: function () { +}, +_cleanup: function () { +}, +_beforeCallListeners: function () { +}, +_getEffectiveNodes: function () { +return this.domApi.getDistributedNodes(); +} +}); +if (Settings.useShadow) { +Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, { +_setup: function () { +if (!this._observer) { +var root = this.domApi.getOwnerRoot(); +var host = root && root.host; +if (host) { +var self = this; +this._observer = Polymer.dom(host).observeNodes(function () { +self._scheduleNotify(); +}); +this._observer._isContentListener = true; +if (this._hasAttrSelect()) { +Polymer.dom(host).observer.enableShadowAttributeTracking(); +} +} +} +}, +_hasAttrSelect: function () { +var select = this.node.getAttribute('select'); +return select && select.match(/[[.]+/); +}, +_cleanup: function () { +var root = this.domApi.getOwnerRoot(); +var host = root && root.host; +if (host) { +Polymer.dom(host).unobserveNodes(this._observer); +} +this._observer = null; +} +}); +} +}()); +(function () { +var hasDomApi = Polymer.DomApi.hasDomApi; Polymer.Base._addFeature({ _prepShady: function () { this._useContent = this._useContent || Boolean(this._template); @@ -3562,6 +4022,7 @@ _createLocalRoot: function () { this.shadyRoot = this.root; this.shadyRoot._distributionClean = false; +this.shadyRoot._hasDistributed = false; this.shadyRoot._isShadyRoot = true; this.shadyRoot._dirtyRoots = []; var i$ = this.shadyRoot._insertionPoints = !this._notes || this._notes._hasContent ? this.shadyRoot.querySelectorAll('content') : []; @@ -3612,6 +4073,7 @@ this.shadyRoot._distributionClean = true; if (hasInsertionPoint(this.shadyRoot)) { this._composeTree(); +notifyContentObservers(this.shadyRoot); } else { if (!this.shadyRoot._hasDistributed) { this.textContent = ''; @@ -3622,6 +4084,9 @@ this._updateChildNodes(this, children); } } +if (!this.shadyRoot._hasDistributed) { +notifyInitialDistribution(this); +} this.shadyRoot._hasDistributed = true; } }, @@ -3839,6 +4304,19 @@ } } } +function notifyContentObservers(root) { +for (var i = 0, c; i < root._insertionPoints.length; i++) { +c = root._insertionPoints[i]; +if (hasDomApi(c)) { +Polymer.dom(c).notifyObserver(); +} +} +} +function notifyInitialDistribution(host) { +if (hasDomApi(host)) { +Polymer.dom(host).notifyObserver(); +} +} var needsUpgrade = window.CustomElements && !CustomElements.useNative; function upgradeLightChildren(children) { if (needsUpgrade && children) { @@ -3871,20 +4349,23 @@ Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); -this._prepAttributes(); this._prepBehaviors(); this._prepConstructor(); this._prepTemplate(); this._prepShady(); +this._prepPropertyInfo(); }, _prepBehavior: function (b) { this._addHostAttributes(b.hostAttributes); }, _initFeatures: function () { +this._registerHost(); +if (this._template) { this._poolContent(); -this._pushHost(); +this._beginHosting(); this._stampTemplate(); -this._popHost(); +this._endHosting(); +} this._marshalHostAttributes(); this._setupDebouncers(); this._marshalBehaviors(); @@ -3898,35 +4379,79 @@ parseAnnotations: function (template) { var list = []; var content = template._content || template.content; -this._parseNodeAnnotations(content, list); +this._parseNodeAnnotations(content, list, template.hasAttribute('strip-whitespace')); return list; }, -_parseNodeAnnotations: function (node, list) { -return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list); +_parseNodeAnnotations: function (node, list, stripWhiteSpace) { +return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list, stripWhiteSpace); }, -_testEscape: function (value) { -var escape = value.slice(0, 2); -if (escape === '{{' || escape === '[[') { -return escape; +_bindingRegex: /([^{[]*)(\{\{|\[\[)(?!\}\}|\]\])(.+?)(?:\]\]|\}\})/g, +_parseBindings: function (text) { +var re = this._bindingRegex; +var parts = []; +var m, lastIndex; +while ((m = re.exec(text)) !== null) { +if (m[1]) { +parts.push({ literal: m[1] }); +} +var mode = m[2][0]; +var value = m[3].trim(); +var negate = false; +if (value[0] == '!') { +negate = true; +value = value.substring(1).trim(); +} +var customEvent, notifyEvent, colon; +if (mode == '{' && (colon = value.indexOf('::')) > 0) { +notifyEvent = value.substring(colon + 2); +value = value.substring(0, colon); +customEvent = true; +} +parts.push({ +compoundIndex: parts.length, +value: value, +mode: mode, +negate: negate, +event: notifyEvent, +customEvent: customEvent +}); +lastIndex = re.lastIndex; +} +if (lastIndex && lastIndex < text.length) { +var literal = text.substring(lastIndex); +if (literal) { +parts.push({ literal: literal }); +} +} +if (parts.length) { +return parts; } }, +_literalFromParts: function (parts) { +var s = ''; +for (var i = 0; i < parts.length; i++) { +var literal = parts[i].literal; +s += literal || ''; +} +return s; +}, _parseTextNodeAnnotation: function (node, list) { -var v = node.textContent; -var escape = this._testEscape(v); -if (escape) { -node.textContent = ' '; +var parts = this._parseBindings(node.textContent); +if (parts) { +node.textContent = this._literalFromParts(parts) || ' '; var annote = { bindings: [{ kind: 'text', -mode: escape[0], -value: v.slice(2, -2).trim() +name: 'textContent', +parts: parts, +isCompound: parts.length !== 1 }] }; list.push(annote); return annote; } }, -_parseElementAnnotations: function (element, list) { +_parseElementAnnotations: function (element, list, stripWhiteSpace) { var annote = { bindings: [], events: [] @@ -3934,7 +4459,7 @@ if (element.localName === 'content') { list._hasContent = true; } -this._parseChildNodesAnnotations(element, annote, list); +this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace); if (element.attributes) { this._parseNodeAttributeAnnotations(element, annote, list); if (this.prepElement) { @@ -3946,26 +4471,38 @@ } return annote; }, -_parseChildNodesAnnotations: function (root, annote, list, callback) { +_parseChildNodesAnnotations: function (root, annote, list, stripWhiteSpace) { if (root.firstChild) { -for (var i = 0, node = root.firstChild; node; node = node.nextSibling, i++) { +var node = root.firstChild; +var i = 0; +while (node) { +var next = node.nextSibling; if (node.localName === 'template' && !node.hasAttribute('preserve-content')) { this._parseTemplate(node, i, list, annote); } if (node.nodeType === Node.TEXT_NODE) { -var n = node.nextSibling; +var n = next; while (n && n.nodeType === Node.TEXT_NODE) { node.textContent += n.textContent; +next = n.nextSibling; root.removeChild(n); -n = n.nextSibling; +n = next; +} +if (stripWhiteSpace && !node.textContent.trim()) { +root.removeChild(node); +i--; } } -var childAnnotation = this._parseNodeAnnotations(node, list, callback); +if (node.parentNode) { +var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace); if (childAnnotation) { childAnnotation.parent = annote; childAnnotation.index = i; } } +node = next; +i++; +} } }, _parseTemplate: function (node, index, list, parent) { @@ -3981,62 +4518,50 @@ }); }, _parseNodeAttributeAnnotations: function (node, annotation) { -for (var i = node.attributes.length - 1, a; a = node.attributes[i]; i--) { -var n = a.name, v = a.value; -if (n === 'id' && !this._testEscape(v)) { -annotation.id = v; -} else if (n.slice(0, 3) === 'on-') { +var attrs = Array.prototype.slice.call(node.attributes); +for (var i = attrs.length - 1, a; a = attrs[i]; i--) { +var n = a.name; +var v = a.value; +var b; +if (n.slice(0, 3) === 'on-') { node.removeAttribute(n); annotation.events.push({ name: n.slice(3), value: v }); -} else { -var b = this._parseNodeAttributeAnnotation(node, n, v); -if (b) { +} else if (b = this._parseNodeAttributeAnnotation(node, n, v)) { annotation.bindings.push(b); -} +} else if (n === 'id') { +annotation.id = v; } } }, -_parseNodeAttributeAnnotation: function (node, n, v) { -var escape = this._testEscape(v); -if (escape) { -var customEvent; -var name = n; -var mode = escape[0]; -v = v.slice(2, -2).trim(); -var not = false; -if (v[0] == '!') { -v = v.substring(1); -not = true; -} +_parseNodeAttributeAnnotation: function (node, name, value) { +var parts = this._parseBindings(value); +if (parts) { +var origName = name; var kind = 'property'; -if (n[n.length - 1] == '$') { -name = n.slice(0, -1); +if (name[name.length - 1] == '$') { +name = name.slice(0, -1); kind = 'attribute'; } -var notifyEvent, colon; -if (mode == '{' && (colon = v.indexOf('::')) > 0) { -notifyEvent = v.substring(colon + 2); -v = v.substring(0, colon); -customEvent = true; +var literal = this._literalFromParts(parts); +if (literal && kind == 'attribute') { +node.setAttribute(name, literal); } -if (node.localName == 'input' && n == 'value') { -node.setAttribute(n, ''); +if (node.localName == 'input' && name == 'value') { +node.setAttribute(origName, ''); } -node.removeAttribute(n); +node.removeAttribute(origName); if (kind === 'property') { name = Polymer.CaseMap.dashToCamelCase(name); } return { kind: kind, -mode: mode, name: name, -value: v, -negate: not, -event: notifyEvent, -customEvent: customEvent +parts: parts, +literal: literal, +isCompound: parts.length !== 1 }; } }, @@ -4112,7 +4637,10 @@ if (!this._template) { this._notes = []; } else { -Polymer.Annotations.prepElement = this._prepElement.bind(this); +var self = this; +Polymer.Annotations.prepElement = function (element) { +self._prepElement(element); +}; if (this._template._content && this._template._content._notes) { this._notes = this._template._content._notes; } else { @@ -4127,9 +4655,14 @@ var note = notes[i]; for (var j = 0; j < note.bindings.length; j++) { var b = note.bindings[j]; -b.signature = this._parseMethod(b.value); -if (!b.signature) { -b.model = this._modelForPath(b.value); +for (var k = 0; k < b.parts.length; k++) { +var p = b.parts[k]; +if (!p.literal) { +p.signature = this._parseMethod(p.value); +if (!p.signature) { +p.model = this._modelForPath(p.value); +} +} } } if (note.templateContent) { @@ -4140,10 +4673,12 @@ bindings.push({ index: note.index, kind: 'property', -mode: '{', name: '_parent_' + prop, +parts: [{ +mode: '{', model: prop, value: prop +}] }); } note.bindings = note.bindings.concat(bindings); @@ -4152,22 +4687,24 @@ }, _discoverTemplateParentProps: function (notes) { var pp = {}; -notes.forEach(function (n) { -n.bindings.forEach(function (b) { -if (b.signature) { -var args = b.signature.args; -for (var k = 0; k < args.length; k++) { -pp[args[k].model] = true; +for (var i = 0, n; i < notes.length && (n = notes[i]); i++) { +for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) { +for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) { +if (p.signature) { +var args = p.signature.args; +for (var kk = 0; kk < args.length; kk++) { +pp[args[kk].model] = true; } } else { -pp[b.model] = true; +pp[p.model] = true; } -}); +} +} if (n.templateContent) { var tpp = n.templateContent._parentProps; Polymer.Base.mixin(pp, tpp); } -}); +} return pp; }, _prepElement: function (element) { @@ -4181,56 +4718,86 @@ this._marshalAnnotatedListeners(); } }, -_configureAnnotationReferences: function () { -this._configureTemplateContent(); -}, -_configureTemplateContent: function () { -this._notes.forEach(function (note, i) { -if (note.templateContent) { -this._nodes[i]._content = note.templateContent; +_configureAnnotationReferences: function (config) { +var notes = this._notes; +var nodes = this._nodes; +for (var i = 0; i < notes.length; i++) { +var note = notes[i]; +var node = nodes[i]; +this._configureTemplateContent(note, node); +this._configureCompoundBindings(note, node); } -}, this); +}, +_configureTemplateContent: function (note, node) { +if (note.templateContent) { +node._content = note.templateContent; +} +}, +_configureCompoundBindings: function (note, node) { +var bindings = note.bindings; +for (var i = 0; i < bindings.length; i++) { +var binding = bindings[i]; +if (binding.isCompound) { +var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {}); +var parts = binding.parts; +var literals = new Array(parts.length); +for (var j = 0; j < parts.length; j++) { +literals[j] = parts[j].literal; +} +var name = binding.name; +storage[name] = literals; +if (binding.literal && binding.kind == 'property') { +if (node._configValue) { +node._configValue(name, binding.literal); +} else { +node[name] = binding.literal; +} +} +} +} }, _marshalIdNodes: function () { this.$ = {}; -this._notes.forEach(function (a) { +for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { if (a.id) { this.$[a.id] = this._findAnnotatedNode(this.root, a); } -}, this); +} }, _marshalAnnotatedNodes: function () { -if (this._nodes) { -this._nodes = this._nodes.map(function (a) { -return this._findAnnotatedNode(this.root, a); -}, this); +if (this._notes && this._notes.length) { +var r = new Array(this._notes.length); +for (var i = 0; i < this._notes.length; i++) { +r[i] = this._findAnnotatedNode(this.root, this._notes[i]); +} +this._nodes = r; } }, _marshalAnnotatedListeners: function () { -this._notes.forEach(function (a) { +for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { if (a.events && a.events.length) { var node = this._findAnnotatedNode(this.root, a); -a.events.forEach(function (e) { +for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) { this.listen(node, e.name, e.value); -}, this); } -}, this); +} +} } }); Polymer.Base._addFeature({ listeners: {}, _listenListeners: function (listeners) { -var node, name, key; -for (key in listeners) { -if (key.indexOf('.') < 0) { +var node, name, eventName; +for (eventName in listeners) { +if (eventName.indexOf('.') < 0) { node = this; -name = key; +name = eventName; } else { -name = key.split('.'); +name = eventName.split('.'); node = this.$[name[0]]; name = name[1]; } -this.listen(node, name, listeners[key]); +this.listen(node, name, listeners[eventName]); } }, listen: function (node, eventName, methodName) { @@ -4301,6 +4868,7 @@ }); (function () { 'use strict'; +var wrap = Polymer.DomApi.wrap; var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string'; var GESTURE_KEY = '__polymerGestures'; var HANDLED_OBJ = '__polymerGesturesHandled'; @@ -4451,8 +5019,11 @@ handleNative: function (ev) { var handled; var type = ev.type; -var node = ev.currentTarget; +var node = wrap(ev.currentTarget); var gobj = node[GESTURE_KEY]; +if (!gobj) { +return; +} var gs = gobj[type]; if (!gs) { return; @@ -4535,6 +5106,7 @@ } }, add: function (node, evType, handler) { +node = wrap(node); var recognizer = this.gestures[evType]; var deps = recognizer.deps; var name = recognizer.name; @@ -4563,6 +5135,7 @@ } }, remove: function (node, evType, handler) { +node = wrap(node); var recognizer = this.gestures[evType]; var deps = recognizer.deps; var name = recognizer.name; @@ -4689,7 +5262,9 @@ x: event.clientX, y: event.clientY, sourceEvent: event, -prevent: Gestures.prevent.bind(Gestures) +prevent: function (e) { +return Gestures.prevent(e); +} }); } }); @@ -4981,12 +5556,17 @@ this._lastVal += len; } }; -new (window.MutationObserver || JsMutationObserver)(Polymer.Async._atEndOfMicrotask.bind(Polymer.Async)).observe(Polymer.Async._twiddle, { characterData: true }); +new window.MutationObserver(function () { +Polymer.Async._atEndOfMicrotask(); +}).observe(Polymer.Async._twiddle, { characterData: true }); Polymer.Debounce = function () { var Async = Polymer.Async; var Debouncer = function (context) { this.context = context; -this.boundComplete = this.complete.bind(this); +var self = this; +this.boundComplete = function () { +self.complete(); +}; }; Debouncer.prototype = { go: function (callback, wait) { @@ -5063,6 +5643,32 @@ Polymer.dom(toElement).setAttribute(name, ''); } }, +getEffectiveChildNodes: function () { +return Polymer.dom(this).getEffectiveChildNodes(); +}, +getEffectiveChildren: function () { +var list = Polymer.dom(this).getEffectiveChildNodes(); +return list.filter(function (n) { +return n.nodeType === Node.ELEMENT_NODE; +}); +}, +getEffectiveTextContent: function () { +var cn = this.getEffectiveChildNodes(); +var tc = []; +for (var i = 0, c; c = cn[i]; i++) { +if (c.nodeType !== Node.COMMENT_NODE) { +tc.push(Polymer.dom(c).textContent); +} +} +return tc.join(''); +}, +queryEffectiveChildren: function (slctr) { +var e$ = Polymer.dom(this).queryDistributedElements(slctr); +return e$ && e$[0]; +}, +queryAllEffectiveChildren: function (slctr) { +return Polymer.dom(this).queryDistributedElements(slctr); +}, getContentChildNodes: function (slctr) { var content = Polymer.dom(this.root).querySelector(slctr || 'content'); return content ? Polymer.dom(content).getDistributedNodes() : []; @@ -5075,19 +5681,37 @@ fire: function (type, detail, options) { options = options || Polymer.nob; var node = options.node || this; -var detail = detail === null || detail === undefined ? Polymer.nob : detail; +var detail = detail === null || detail === undefined ? {} : detail; var bubbles = options.bubbles === undefined ? true : options.bubbles; var cancelable = Boolean(options.cancelable); -var event = new CustomEvent(type, { -bubbles: Boolean(bubbles), -cancelable: cancelable, -detail: detail -}); +var useCache = options._useCache; +var event = this._getEvent(type, bubbles, cancelable, useCache); +event.detail = detail; +if (useCache) { +this.__eventCache[type] = null; +} node.dispatchEvent(event); +if (useCache) { +this.__eventCache[type] = event; +} +return event; +}, +__eventCache: {}, +_getEvent: function (type, bubbles, cancelable, useCache) { +var event = useCache && this.__eventCache[type]; +if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) { +event = new Event(type, { +bubbles: Boolean(bubbles), +cancelable: cancelable +}); +} return event; }, async: function (callback, waitTime) { -return Polymer.Async.run(callback.bind(this), waitTime); +var self = this; +return Polymer.Async.run(function () { +callback.call(self); +}, waitTime); }, cancelAsync: function (handle) { Polymer.Async.cancel(handle); @@ -5100,7 +5724,7 @@ return path.splice(index, 1); } } else { -var arr = this.get(path); +var arr = this._get(path); index = arr.indexOf(item); if (index >= 0) { return this.splice(path, index, 1); @@ -5120,11 +5744,16 @@ var l = document.createElement('link'); l.rel = 'import'; l.href = href; +var self = this; if (onload) { -l.onload = onload.bind(this); +l.onload = function (e) { +return onload.call(self, e); +}; } if (onerror) { -l.onerror = onerror.bind(this); +l.onerror = function (e) { +return onerror.call(self, e); +}; } document.head.appendChild(l); return l; @@ -5139,24 +5768,25 @@ return elt; }, isLightDescendant: function (node) { -return this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot(); +return this !== node && this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot(); }, isLocalDescendant: function (node) { return this.root === Polymer.dom(node).getOwnerRoot(); } }); Polymer.Bind = { +_dataEventCache: {}, prepareModel: function (model) { -model._propertyEffects = {}; -model._bindListeners = []; Polymer.Base.mixin(model, this._modelApi); }, _modelApi: { -_notifyChange: function (property) { -var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed'; -Polymer.Base.fire(eventName, { value: this[property] }, { +_notifyChange: function (source, event, value) { +value = value === undefined ? this[source] : value; +event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed'; +this.fire(event, { value: value }, { bubbles: false, -node: this +cancelable: false, +_useCache: true }); }, _propertySetter: function (property, value, effects, fromAbove) { @@ -5185,12 +5815,9 @@ } }, _effectEffects: function (property, value, effects, old, fromAbove) { -effects.forEach(function (fx) { -var fn = Polymer.Bind['_' + fx.kind + 'Effect']; -if (fn) { -fn.call(this, property, value, fx.effect, old, fromAbove); +for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) { +fx.fn.call(this, property, value, fx.effect, old, fromAbove); } -}, this); }, _clearPath: function (path) { for (var prop in this.__data__) { @@ -5201,6 +5828,9 @@ } }, ensurePropertyEffects: function (model, property) { +if (!model._propertyEffects) { +model._propertyEffects = {}; +} var fx = model._propertyEffects[property]; if (!fx) { fx = model._propertyEffects[property] = []; @@ -5209,10 +5839,13 @@ }, addPropertyEffect: function (model, property, kind, effect) { var fx = this.ensurePropertyEffects(model, property); -fx.push({ +var propEffect = { kind: kind, -effect: effect -}); +effect: effect, +fn: Polymer.Bind['_' + kind + 'Effect'] +}; +fx.push(propEffect); +return propEffect; }, createBindings: function (model) { var fx$ = model._propertyEffects; @@ -5262,7 +5895,10 @@ 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); +if (!model._bindListeners) { +model._bindListeners = []; +} +var fn = this._notedListenerFactory(property, path, this._isStructured(path)); var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed'; model._bindListeners.push({ index: index, @@ -5278,54 +5914,59 @@ _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); +_notedListenerFactory: function (property, path, isStructured) { +return function (target, value, targetPath) { +if (targetPath) { +this._notifyPath(this._fixPath(path, property, targetPath), value); } else { -var value = target[property]; +value = target[property]; if (!isStructured) { -this[path] = target[property]; +this[path] = value; } else { if (this.__data__[path] != value) { this.set(path, value); } } } -} }; }, prepareInstance: function (inst) { inst.__data__ = Object.create(null); }, setupBindListeners: function (inst) { -inst._bindListeners.forEach(function (info) { +var b$ = inst._bindListeners; +for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) { var node = inst._nodes[info.index]; -node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn)); +this._addNotifyListener(node, inst, info.event, info.changedFn); +} +; +}, +_addNotifyListener: function (element, context, event, changedFn) { +element.addEventListener(event, function (e) { +return context._notifyListener(changedFn, e); }); } }; Polymer.Base.extend(Polymer.Bind, { _shouldAddListener: function (effect) { -return effect.name && effect.mode === '{' && !effect.negate && effect.kind != 'attribute'; +return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !effect.isCompound && effect.parts[0].mode === '{' && !effect.parts[0].negate; }, _annotationEffect: function (source, value, effect) { if (source != effect.value) { -value = this.get(effect.value); +value = this._get(effect.value); this.__data__[effect.value] = value; } var calc = effect.negate ? !value : value; if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) { -return this._applyEffectValue(calc, effect); +return this._applyEffectValue(effect, calc); } }, -_reflectEffect: function (source) { -this.reflectPropertyToAttribute(source); +_reflectEffect: function (source, value, effect) { +this.reflectPropertyToAttribute(source, effect.attribute, value); }, _notifyEffect: function (source, value, effect, old, fromAbove) { if (!fromAbove) { -this._notifyChange(source); +this._notifyChange(source, effect.event, value); } }, _functionEffect: function (source, value, fn, old, fromAbove) { @@ -5355,7 +5996,7 @@ if (args) { var fn = this[effect.method]; if (fn) { -this.__setProperty(effect.property, fn.apply(this, args)); +this.__setProperty(effect.name, fn.apply(this, args)); } else { this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined')); } @@ -5371,7 +6012,7 @@ if (effect.negate) { computedvalue = !computedvalue; } -this._applyEffectValue(computedvalue, effect); +this._applyEffectValue(effect, computedvalue); } } else { computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute method `' + effect.method + '` not defined')); @@ -5387,7 +6028,7 @@ if (arg.literal) { v = arg.value; } else if (arg.structured) { -v = Polymer.Base.get(name, model); +v = Polymer.Base._get(name, model); } else { v = model[name]; } @@ -5411,7 +6052,8 @@ }); Polymer.Base._addFeature({ _addPropertyEffect: function (property, kind, effect) { -Polymer.Bind.addPropertyEffect(this, property, kind, effect); +var prop = Polymer.Bind.addPropertyEffect(this, property, kind, effect); +prop.pathFn = this['_' + prop.kind + 'PathEffect']; }, _prepEffects: function () { Polymer.Bind.prepareModel(this); @@ -5432,10 +6074,10 @@ this._addComputedEffect(p, prop.computed); } if (prop.notify) { -this._addPropertyEffect(p, 'notify'); +this._addPropertyEffect(p, 'notify', { event: Polymer.CaseMap.camelToDashCase(p) + '-changed' }); } if (prop.reflectToAttribute) { -this._addPropertyEffect(p, 'reflect'); +this._addPropertyEffect(p, 'reflect', { attribute: Polymer.CaseMap.camelToDashCase(p) }); } if (prop.readOnly) { Polymer.Bind.ensurePropertyEffects(this, p); @@ -5445,14 +6087,14 @@ }, _addComputedEffect: function (name, expression) { var sig = this._parseMethod(expression); -sig.args.forEach(function (arg) { +for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { this._addPropertyEffect(arg.model, 'compute', { method: sig.method, args: sig.args, trigger: arg, -property: name +name: name }); -}, this); +} }, _addObserverEffect: function (property, observer) { this._addPropertyEffect(property, 'observer', { @@ -5462,61 +6104,74 @@ }, _addComplexObserverEffects: function (observers) { if (observers) { -observers.forEach(function (observer) { -this._addComplexObserverEffect(observer); -}, this); +for (var i = 0, o; i < observers.length && (o = observers[i]); i++) { +this._addComplexObserverEffect(o); +} } }, _addComplexObserverEffect: function (observer) { var sig = this._parseMethod(observer); -sig.args.forEach(function (arg) { +for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { this._addPropertyEffect(arg.model, 'complexObserver', { method: sig.method, args: sig.args, trigger: arg }); -}, this); +} }, _addAnnotationEffects: function (notes) { -this._nodes = []; -notes.forEach(function (note) { -var index = this._nodes.push(note) - 1; -note.bindings.forEach(function (binding) { -this._addAnnotationEffect(binding, index); -}, this); -}, this); +for (var i = 0, note; i < notes.length && (note = notes[i]); i++) { +var b$ = note.bindings; +for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) { +this._addAnnotationEffect(binding, i); +} +} }, _addAnnotationEffect: function (note, index) { if (Polymer.Bind._shouldAddListener(note)) { -Polymer.Bind._addAnnotatedListener(this, index, note.name, note.value, note.event); +Polymer.Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event); } -if (note.signature) { -this._addAnnotatedComputationEffect(note, index); -} else { -note.index = index; -this._addPropertyEffect(note.model, 'annotation', note); +for (var i = 0; i < note.parts.length; i++) { +var part = note.parts[i]; +if (part.signature) { +this._addAnnotatedComputationEffect(note, part, index); +} else if (!part.literal) { +this._addPropertyEffect(part.model, 'annotation', { +kind: note.kind, +index: index, +name: note.name, +value: part.value, +isCompound: note.isCompound, +compoundIndex: part.compoundIndex, +event: part.event, +customEvent: part.customEvent, +negate: part.negate +}); +} } }, -_addAnnotatedComputationEffect: function (note, index) { -var sig = note.signature; +_addAnnotatedComputationEffect: function (note, part, index) { +var sig = part.signature; if (sig.static) { -this.__addAnnotatedComputationEffect('__static__', index, note, sig, null); +this.__addAnnotatedComputationEffect('__static__', index, note, part, null); } else { -sig.args.forEach(function (arg) { +for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { if (!arg.literal) { -this.__addAnnotatedComputationEffect(arg.model, index, note, sig, arg); +this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg); } -}, this); +} } }, -__addAnnotatedComputationEffect: function (property, index, note, sig, trigger) { +__addAnnotatedComputationEffect: function (property, index, note, part, trigger) { this._addPropertyEffect(property, 'annotatedComputation', { index: index, +isCompound: note.isCompound, +compoundIndex: part.compoundIndex, kind: note.kind, -property: note.name, -negate: note.negate, -method: sig.method, -args: sig.args, +name: note.name, +negate: part.negate, +method: part.signature.method, +args: part.signature.args, trigger: trigger }); }, @@ -5583,11 +6238,18 @@ }, _marshalInstanceEffects: function () { Polymer.Bind.prepareInstance(this); +if (this._bindListeners) { Polymer.Bind.setupBindListeners(this); +} }, -_applyEffectValue: function (value, info) { +_applyEffectValue: function (info, value) { var node = this._nodes[info.index]; -var property = info.property || info.name || 'textContent'; +var property = info.name; +if (info.isCompound) { +var storage = node.__compoundStorage__[property]; +storage[info.compoundIndex] = value; +value = storage.join(''); +} if (info.kind == 'attribute') { this.serializeValueToAttribute(value, property, node); } else { @@ -5597,11 +6259,14 @@ if (property === 'textContent' || node.localName == 'input' && property == 'value') { value = value == undefined ? '' : value; } -return node[property] = value; +var pinfo; +if (!node._propertyInfo || !(pinfo = node._propertyInfo[property]) || !pinfo.readOnly) { +this.__setProperty(property, value, true, node); +} } }, _executeStaticEffects: function () { -if (this._propertyEffects.__static__) { +if (this._propertyEffects && this._propertyEffects.__static__) { this._effectEffects('__static__', null, this._propertyEffects.__static__); } } @@ -5609,12 +6274,14 @@ Polymer.Base._addFeature({ _setupConfigure: function (initialConfig) { this._config = {}; +this._handlers = []; +if (initialConfig) { for (var i in initialConfig) { if (initialConfig[i] !== undefined) { this._config[i] = initialConfig[i]; } } -this._handlers = []; +} }, _marshalAttributes: function () { this._takeAttributesToModel(this._config); @@ -5624,7 +6291,10 @@ this._setAttributeToProperty(model, name); }, _configValue: function (name, value) { +var info = this._propertyInfo[name]; +if (!info || !info.readOnly) { this._config[name] = value; +} }, _beforeClientsReady: function () { this._configure(); @@ -5633,13 +6303,15 @@ this._configureAnnotationReferences(); this._aboveConfig = this.mixin({}, this._config); var config = {}; -this.behaviors.forEach(function (b) { -this._configureProperties(b.properties, config); -}, this); +for (var i = 0; i < this.behaviors.length; i++) { +this._configureProperties(this.behaviors[i].properties, config); +} this._configureProperties(this.properties, config); -this._mixinConfigure(config, this._aboveConfig); +this.mixin(config, this._aboveConfig); this._config = config; +if (this._clients && this._clients.length) { this._distributeConfig(this._config); +} }, _configureProperties: function (properties, config) { for (var i in properties) { @@ -5653,13 +6325,6 @@ } } }, -_mixinConfigure: function (a, b) { -for (var prop in b) { -if (!this.getPropertyInfo(prop).readOnly) { -a[prop] = b[prop]; -} -} -}, _distributeConfig: function (config) { var fx$ = this._propertyEffects; if (fx$) { @@ -5667,10 +6332,10 @@ var fx = fx$[p]; if (fx) { for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) { -if (x.kind === 'annotation') { +if (x.kind === 'annotation' && !x.isCompound) { var node = this._nodes[x.effect.index]; if (node._configValue) { -var value = p === x.effect.value ? config[p] : this.get(x.effect.value, config); +var value = p === x.effect.value ? config[p] : this._get(x.effect.value, config); node._configValue(x.effect.name, value); } } @@ -5692,14 +6357,22 @@ } }, _notifyListener: function (fn, e) { +if (!Polymer.Bind._isEventBogus(e, e.target)) { +var value, path; +if (e.detail) { +value = e.detail.value; +path = e.detail.path; +} if (!this._clientsReadied) { this._queueHandler([ fn, -e, -e.target +e.target, +value, +path ]); } else { -return fn.call(this, e, e.target); +return fn.call(this, e.target, value, path); +} } }, _queueHandler: function (args) { @@ -5708,7 +6381,7 @@ _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]); +h[0].call(this, h[1], h[2], h[3]); } this._handlers = []; } @@ -5717,11 +6390,16 @@ 'use strict'; Polymer.Base._addFeature({ notifyPath: function (path, value, fromAbove) { +var info = {}; +this._get(path, this, info); +this._notifyPath(info.path, value, fromAbove); +}, +_notifyPath: function (path, value, fromAbove) { var old = this._propertySetter(path, value); if (old !== value && (old === old || value === value)) { this._pathEffector(path, value); if (!fromAbove) { -this._notifyPath(path, value); +this._notifyPathUp(path, value); } return true; } @@ -5748,52 +6426,78 @@ if (parts.length > 1) { for (var i = 0; i < parts.length - 1; i++) { var part = parts[i]; +if (array && part[0] == '#') { +prop = Polymer.Collection.get(array).getItem(part); +} else { prop = prop[part]; -if (array && parseInt(part) == part) { +if (array && parseInt(part, 10) == part) { parts[i] = Polymer.Collection.get(array).getKey(prop); } +} if (!prop) { return; } array = Array.isArray(prop) ? prop : null; } -if (array && parseInt(last) == last) { +if (array) { var coll = Polymer.Collection.get(array); +if (last[0] == '#') { +var key = last; +var old = coll.getItem(key); +last = array.indexOf(old); +coll.setItem(key, value); +} else if (parseInt(last, 10) == last) { var old = prop[last]; var key = coll.getKey(old); parts[i] = key; coll.setItem(key, value); } +} prop[last] = value; if (!root) { -this.notifyPath(parts.join('.'), value); +this._notifyPath(parts.join('.'), value); } } else { prop[path] = value; } }, get: function (path, root) { +return this._get(path, root); +}, +_get: function (path, root, info) { var prop = root || this; var parts = this._getPathParts(path); -var last = parts.pop(); -while (parts.length) { -prop = prop[parts.shift()]; +var array; +for (var i = 0; i < parts.length; i++) { if (!prop) { return; } +var part = parts[i]; +if (array && part[0] == '#') { +prop = Polymer.Collection.get(array).getItem(part); +} else { +prop = prop[part]; +if (info && array && parseInt(part, 10) == part) { +parts[i] = Polymer.Collection.get(array).getKey(prop); } -return prop[last]; +} +array = Array.isArray(prop) ? prop : null; +} +if (info) { +info.path = parts.join('.'); +} +return prop; }, _pathEffector: function (path, value) { var model = this._modelForPath(path); -var fx$ = this._propertyEffects[model]; +var fx$ = this._propertyEffects && this._propertyEffects[model]; if (fx$) { -fx$.forEach(function (fx) { -var fxFn = this['_' + fx.kind + 'PathEffect']; +for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) { +var fxFn = fx.pathFn; if (fxFn) { fxFn.call(this, path, value, fx.effect); } -}, this); +} } if (this._boundPaths) { this._notifyBoundPaths(path, value); @@ -5804,9 +6508,9 @@ Polymer.Bind._annotationEffect.call(this, path, value, effect); } else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) { var node = this._nodes[effect.index]; -if (node && node.notifyPath) { +if (node && node._notifyPath) { var p = this._fixPath(effect.name, effect.value, path); -node.notifyPath(p, value, true); +node._notifyPath(p, value, true); } } }, @@ -5846,70 +6550,88 @@ for (var a in this._boundPaths) { var b = this._boundPaths[a]; if (path.indexOf(a + '.') == 0) { -this.notifyPath(this._fixPath(b, a, path), value); +this._notifyPath(this._fixPath(b, a, path), value); } else if (path.indexOf(b + '.') == 0) { -this.notifyPath(this._fixPath(a, b, path), value); +this._notifyPath(this._fixPath(a, b, path), value); } } }, _fixPath: function (property, root, path) { return property + path.slice(root.length); }, -_notifyPath: function (path, value) { +_notifyPathUp: 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 }); +}, { +bubbles: false, +_useCache: true +}); }, _modelForPath: function (path) { var dot = path.indexOf('.'); return dot < 0 ? path : path.slice(0, dot); }, _EVENT_CHANGED: '-changed', +notifySplices: function (path, splices) { +var info = {}; +var array = this._get(path, this, info); +this._notifySplices(array, info.path, splices); +}, +_notifySplices: function (array, path, splices) { +var change = { +keySplices: Polymer.Collection.applySplices(array, splices), +indexSplices: splices +}; +if (!array.hasOwnProperty('splices')) { +Object.defineProperty(array, 'splices', { +configurable: true, +writable: true +}); +} +array.splices = change; +this._notifyPath(path + '.splices', change); +this._notifyPath(path + '.length', array.length); +change.keySplices = null; +change.indexSplices = null; +}, _notifySplice: function (array, path, index, added, removed) { -var splices = [{ +this._notifySplices(array, path, [{ index: index, addedCount: added, removed: removed, object: array, type: 'splice' -}]; -var change = { -keySplices: Polymer.Collection.applySplices(array, splices), -indexSplices: splices -}; -this.set(path + '.splices', change); -if (added != removed.length) { -this.notifyPath(path + '.length', array.length); -} -change.keySplices = null; -change.indexSplices = null; +}]); }, push: function (path) { -var array = this.get(path); +var info = {}; +var array = this._get(path, this, info); var args = Array.prototype.slice.call(arguments, 1); var len = array.length; var ret = array.push.apply(array, args); if (args.length) { -this._notifySplice(array, path, len, args.length, []); +this._notifySplice(array, info.path, len, args.length, []); } return ret; }, pop: function (path) { -var array = this.get(path); +var info = {}; +var array = this._get(path, this, info); var hadLength = Boolean(array.length); var args = Array.prototype.slice.call(arguments, 1); var ret = array.pop.apply(array, args); if (hadLength) { -this._notifySplice(array, path, array.length, 0, [ret]); +this._notifySplice(array, info.path, array.length, 0, [ret]); } return ret; }, splice: function (path, start, deleteCount) { -var array = this.get(path); +var info = {}; +var array = this._get(path, this, info); if (start < 0) { start = array.length - Math.floor(-start); } else { @@ -5922,35 +6644,41 @@ var ret = array.splice.apply(array, args); var addedCount = Math.max(args.length - 2, 0); if (addedCount || ret.length) { -this._notifySplice(array, path, start, addedCount, ret); +this._notifySplice(array, info.path, start, addedCount, ret); } return ret; }, shift: function (path) { -var array = this.get(path); +var info = {}; +var array = this._get(path, this, info); var hadLength = Boolean(array.length); var args = Array.prototype.slice.call(arguments, 1); var ret = array.shift.apply(array, args); if (hadLength) { -this._notifySplice(array, path, 0, 0, [ret]); +this._notifySplice(array, info.path, 0, 0, [ret]); } return ret; }, unshift: function (path) { -var array = this.get(path); +var info = {}; +var array = this._get(path, this, info); var args = Array.prototype.slice.call(arguments, 1); var ret = array.unshift.apply(array, args); if (args.length) { -this._notifySplice(array, path, 0, args.length, []); +this._notifySplice(array, info.path, 0, args.length, []); } return ret; }, prepareModelNotifyPath: function (model) { this.mixin(model, { fire: Polymer.Base.fire, +_getEvent: Polymer.Base._getEvent, +__eventCache: Polymer.Base.__eventCache, notifyPath: Polymer.Base.notifyPath, +_get: Polymer.Base._get, _EVENT_CHANGED: Polymer.Base._EVENT_CHANGED, _notifyPath: Polymer.Base._notifyPath, +_notifyPathUp: Polymer.Base._notifyPathUp, _pathEffector: Polymer.Base._pathEffector, _annotationPathEffect: Polymer.Base._annotationPathEffect, _complexObserverPathEffect: Polymer.Base._complexObserverPathEffect, @@ -5958,7 +6686,8 @@ _computePathEffect: Polymer.Base._computePathEffect, _modelForPath: Polymer.Base._modelForPath, _pathMatchesEffect: Polymer.Base._pathMatchesEffect, -_notifyBoundPaths: Polymer.Base._notifyBoundPaths +_notifyBoundPaths: Polymer.Base._notifyBoundPaths, +_getPathParts: Polymer.Base._getPathParts }); } }); @@ -6018,6 +6747,8 @@ if (node.parent) { var ss = node.previous ? node.previous.end : node.parent.start; t = text.substring(ss, node.start - 1); +t = this._expandUnicodeEscapes(t); +t = t.replace(this._rx.multipleSpaces, ' '); t = t.substring(t.lastIndexOf(';') + 1); var s = node.parsedSelector = node.selector = t.trim(); node.atRule = s.indexOf(this.AT_START) === 0; @@ -6043,6 +6774,15 @@ } return node; }, +_expandUnicodeEscapes: function (s) { +return s.replace(/\\([0-9a-f]{1,6})\s/gi, function () { +var code = arguments[1], repeat = 6 - code.length; +while (repeat--) { +code = '0' + code; +} +return '\\' + code; +}); +}, stringify: function (node, preserveProperties, text) { text = text || ''; var cssText = ''; @@ -6072,7 +6812,7 @@ return text; }, _hasMixinRules: function (rules) { -return rules[0].selector.indexOf(this.VAR_START) >= 0; +return rules[0].selector.indexOf(this.VAR_START) === 0; }, removeCustomProps: function (cssText) { return cssText; @@ -6095,10 +6835,11 @@ comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim, port: /@import[^;]*;/gim, customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim, -mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim, +mixinProp: /(?:^|[\s;])?--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim, mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim, -varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim, -keyframesRule: /^@[^\s]*keyframes/ +varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim, +keyframesRule: /^@[^\s]*keyframes/, +multipleSpaces: /\s+/g }, VAR_START: '--', MEDIA_START: '@media', @@ -6178,21 +6919,21 @@ cssFromModule: function (moduleId, warnIfNotFound) { var m = Polymer.DomModule.import(moduleId); if (m && !m._cssText) { -m._cssText = this._cssFromElement(m); +m._cssText = this.cssFromElement(m); } if (!m && warnIfNotFound) { console.warn('Could not find style data in module named', moduleId); } return m && m._cssText || ''; }, -_cssFromElement: function (element) { +cssFromElement: function (element) { var cssText = ''; var content = element.content || element; -var e$ = Array.prototype.slice.call(content.querySelectorAll(this.MODULE_STYLES_SELECTOR)); +var e$ = Polymer.DomApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR)); for (var i = 0, e; i < e$.length; i++) { e = e$[i]; if (e.localName === 'template') { -cssText += this._cssFromElement(e); +cssText += this.cssFromElement(e); } else { if (e.localName === 'style') { var include = e.getAttribute(this.INCLUDE_ATTR); @@ -6441,7 +7182,7 @@ if (target.parent !== source.parent) { this._cloneAndAddRuleToParent(source, target.parent); } -target.extends = target.extends || (target.extends = []); +target.extends = target.extends || []; target.extends.push(source); source.selector = source.selector.replace(this.rx.STRIP, ''); source.selector = (source.selector && source.selector + ',\n') + target.selector; @@ -6482,14 +7223,18 @@ if (this._encapsulateStyle === undefined) { this._encapsulateStyle = !nativeShadow && Boolean(this._template); } +if (this._template) { this._styles = this._collectStyles(); var cssText = styleTransformer.elementStyles(this); -if (cssText && this._template) { +if (cssText) { var style = styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : null); if (!nativeShadow) { this._scopeStyle = style; } } +} else { +this._styles = []; +} }, _collectStyles: function () { var styles = []; @@ -6500,6 +7245,10 @@ } } cssText += styleUtil.cssFromModule(this.is); +var p = this._template && this._template.parentNode; +if (this._template && (!p || p.id.toLowerCase() !== this.is)) { +cssText += styleUtil.cssFromElement(this._template); +} if (cssText) { var style = document.createElement('style'); style.textContent = cssText; @@ -6533,21 +7282,21 @@ if (node.nodeType === Node.ELEMENT_NODE) { node.className = self._scopeElementClass(node, node.className); var n$ = node.querySelectorAll('*'); -Array.prototype.forEach.call(n$, function (n) { +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { n.className = self._scopeElementClass(n, n.className); -}); +} } }; scopify(container); if (shouldObserve) { var mo = new MutationObserver(function (mxns) { -mxns.forEach(function (m) { +for (var i = 0, m; i < mxns.length && (m = mxns[i]); i++) { if (m.addedNodes) { -for (var i = 0; i < m.addedNodes.length; i++) { -scopify(m.addedNodes[i]); +for (var j = 0; j < m.addedNodes.length; j++) { +scopify(m.addedNodes[j]); } } -}); +} }); mo.observe(container, { childList: true, @@ -6672,7 +7421,9 @@ parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || ''; } } -return parts.join(';'); +return parts.filter(function (v) { +return v; +}).join(';'); }, applyProperties: function (rule, props) { var output = ''; @@ -6798,7 +7549,7 @@ } }, rx: { -VAR_ASSIGN: /(?:^|[;\n]\s*)(--[\w-]*?):\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\n])|$)/gi, +VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi, MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i, VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi, VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi, @@ -6917,9 +7668,12 @@ var nativeShadow = Polymer.Settings.useNativeShadow; Polymer.Base._addFeature({ _prepStyleProperties: function () { -this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : []; +this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : null; }, -customStyle: {}, +customStyle: null, +getComputedStyleValue: function (property) { +return this._styleProperties && this._styleProperties[property] || getComputedStyle(this).getPropertyValue(property); +}, _setupStyleProperties: function () { this.customStyle = {}; }, @@ -7016,7 +7770,7 @@ value = host._scopeElementClass(node, value); } } -node = Polymer.dom(node); +node = this.shadyRoot && this.shadyRoot._hasDistributed ? Polymer.dom(node) : node; serializeValueToAttribute.call(this, value, attribute, node); }, _scopeElementClass: function (element, selector) { @@ -7065,7 +7819,6 @@ Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); -this._prepAttributes(); this._prepConstructor(); this._prepTemplate(); this._prepStyles(); @@ -7073,6 +7826,7 @@ this._prepAnnotations(); this._prepEffects(); this._prepBehaviors(); +this._prepPropertyInfo(); this._prepBindings(); this._prepShady(); }, @@ -7082,23 +7836,28 @@ this._addHostAttributes(b.hostAttributes); }, _initFeatures: function () { -this._poolContent(); this._setupConfigure(); this._setupStyleProperties(); -this._pushHost(); -this._stampTemplate(); -this._popHost(); -this._marshalAnnotationReferences(); this._setupDebouncers(); +this._registerHost(); +if (this._template) { +this._poolContent(); +this._beginHosting(); +this._stampTemplate(); +this._endHosting(); +this._marshalAnnotationReferences(); +} this._marshalInstanceEffects(); -this._marshalHostAttributes(); this._marshalBehaviors(); +this._marshalHostAttributes(); this._marshalAttributes(); this._tryReady(); }, _marshalBehavior: function (b) { +if (b.listeners) { this._listenListeners(b.listeners); } +} }); (function () { var nativeShadow = Polymer.Settings.useNativeShadow; @@ -7110,6 +7869,7 @@ Polymer({ is: 'custom-style', extends: 'style', +_template: null, properties: { include: String }, ready: function () { this._tryApply(); @@ -7124,18 +7884,19 @@ var e = this.__appliedElement || this; styleDefaults.addStyle(e); if (e.textContent || this.include) { -this._apply(); +this._apply(true); } else { +var self = this; var observer = new MutationObserver(function () { observer.disconnect(); -this._apply(); -}.bind(this)); +self._apply(true); +}); observer.observe(e, { childList: true }); } } } }, -_apply: function () { +_apply: function (deferProperties) { var e = this.__appliedElement || this; if (this.include) { e.textContent = styleUtil.cssFromModules(this.include, true) + e.textContent; @@ -7144,7 +7905,19 @@ styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function (rule) { styleTransformer.documentRule(rule); }); -this._applyCustomProperties(e); +var self = this; +function fn() { +self._applyCustomProperties(e); +} +if (this._pendingApplyProperties) { +cancelAnimationFrame(this._pendingApplyProperties); +this._pendingApplyProperties = null; +} +if (deferProperties) { +this._pendingApplyProperties = requestAnimationFrame(fn); +} else { +fn(); +} } }, _applyCustomProperties: function (element) { @@ -7181,8 +7954,9 @@ archetype._prepEffects(); this._customPrepEffects(archetype); archetype._prepBehaviors(); +archetype._prepPropertyInfo(); archetype._prepBindings(); -archetype._notifyPath = this._notifyPathImpl; +archetype._notifyPathUp = this._notifyPathUpImpl; archetype._scopeElementClass = this._scopeElementClassImpl; archetype.listen = this._listenImpl; archetype._showHideChildren = this._showHideChildrenImpl; @@ -7243,7 +8017,9 @@ if (!c._notes) { var rootDataHost = archetype._rootDataHost; if (rootDataHost) { -Polymer.Annotations.prepElement = rootDataHost._prepElement.bind(rootDataHost); +Polymer.Annotations.prepElement = function () { +rootDataHost._prepElement(); +}; } c._notes = Polymer.Annotations.parseAnnotations(template); Polymer.Annotations.prepElement = null; @@ -7271,19 +8047,29 @@ var effects = [ { kind: 'function', -effect: this._createForwardPropEffector(prop) +effect: this._createForwardPropEffector(prop), +fn: Polymer.Bind._functionEffect }, -{ kind: 'notify' } +{ +kind: 'notify', +fn: Polymer.Bind._notifyEffect, +effect: { event: Polymer.CaseMap.camelToDashCase(parentProp) + '-changed' } +} ]; Polymer.Bind._createAccessors(proto, parentProp, effects); } } +var self = this; if (template != this) { Polymer.Bind.prepareInstance(template); -template._forwardParentProp = this._forwardParentProp.bind(this); +template._forwardParentProp = function (source, value) { +self._forwardParentProp(source, value); +}; } this._extendTemplate(template, proto); -template._pathEffector = this._pathEffectorImpl.bind(this); +template._pathEffector = function (path, value, fromAbove) { +return self._pathEffectorImpl(path, value, fromAbove); +}; } }, _createForwardPropEffector: function (prop) { @@ -7305,14 +8091,15 @@ }; }, _extendTemplate: function (template, proto) { -Object.getOwnPropertyNames(proto).forEach(function (n) { +var n$ = Object.getOwnPropertyNames(proto); +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { var val = template[n]; var pd = Object.getOwnPropertyDescriptor(proto, n); Object.defineProperty(template, n, pd); if (val !== undefined) { template._propertySetter(n, val); } -}); +} }, _showHideChildren: function (hidden) { }, @@ -7320,7 +8107,7 @@ }, _forwardInstanceProp: function (inst, prop, value) { }, -_notifyPathImpl: function (path, value) { +_notifyPathUpImpl: function (path, value) { var dataHost = this.dataHost; var dot = path.indexOf('.'); var root = dot < 0 ? path : path.slice(0, dot); @@ -7333,19 +8120,23 @@ if (this._forwardParentPath) { if (path.indexOf(this._parentPropPrefix) === 0) { var subPath = path.substring(this._parentPropPrefix.length); +var model = this._modelForPath(subPath); +if (model in this._parentProps) { this._forwardParentPath(subPath, value); } } +} Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove); }, _constructorImpl: function (model, host) { this._rootDataHost = host._getRootDataHost(); this._setupConfigure(model); -this._pushHost(host); +this._registerHost(host); +this._beginHosting(); this.root = this.instanceTemplate(this._template); this.root.__noContent = !this._notes._hasContent; this.root.__styleScoped = true; -this._popHost(); +this._endHosting(); this._marshalAnnotatedNodes(); this._marshalInstanceEffects(); this._marshalAnnotatedListeners(); @@ -7404,6 +8195,7 @@ Polymer({ is: 'dom-template', extends: 'template', +_template: null, behaviors: [Polymer.Templatizer], ready: function () { this.templatize(this); @@ -7438,9 +8230,10 @@ } else { this.pmap[item] = key; } -return key; +return '#' + key; }, removeKey: function (key) { +key = this._parseKey(key); this._removeFromMap(this.store[key]); delete this.store[key]; }, @@ -7457,16 +8250,29 @@ return key; }, getKey: function (item) { +var key; if (item && typeof item == 'object') { -return this.omap.get(item); +key = this.omap.get(item); } else { -return this.pmap[item]; +key = this.pmap[item]; +} +if (key != undefined) { +return '#' + key; } }, getKeys: function () { -return Object.keys(this.store); +return Object.keys(this.store).map(function (key) { +return '#' + key; +}); +}, +_parseKey: function (key) { +if (key[0] == '#') { +return key.slice(1); +} +throw new Error('unexpected key ' + key); }, setItem: function (key, item) { +key = this._parseKey(key); var old = this.store[key]; if (old) { this._removeFromMap(old); @@ -7479,6 +8285,7 @@ this.store[key] = item; }, getItem: function (key) { +key = this._parseKey(key); return this.store[key]; }, getItems: function () { @@ -7489,21 +8296,21 @@ return items; }, _applySplices: function (splices) { -var keyMap = {}, key, i; -splices.forEach(function (s) { +var keyMap = {}, key; +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { s.addedKeys = []; -for (i = 0; i < s.removed.length; i++) { -key = this.getKey(s.removed[i]); +for (var j = 0; j < s.removed.length; j++) { +key = this.getKey(s.removed[j]); keyMap[key] = keyMap[key] ? null : -1; } -for (i = 0; i < s.addedCount; i++) { -var item = this.userArray[s.index + i]; +for (var j = 0; j < s.addedCount; j++) { +var item = this.userArray[s.index + j]; key = this.getKey(item); key = key === undefined ? this.add(item) : key; keyMap[key] = keyMap[key] ? null : 1; s.addedKeys.push(key); } -}, this); +} var removed = []; var added = []; for (var key in keyMap) { @@ -7531,6 +8338,7 @@ Polymer({ is: 'dom-repeat', extends: 'template', +_template: null, properties: { items: { type: Array }, as: { @@ -7553,22 +8361,37 @@ type: String, observer: '_observeChanged' }, -delay: Number +delay: Number, +initialCount: { +type: Number, +observer: '_initializeChunking' +}, +targetFramerate: { +type: Number, +value: 20 +}, +_targetFrameTime: { computed: '_computeFrameTime(targetFramerate)' } }, behaviors: [Polymer.Templatizer], observers: ['_itemsChanged(items.*)'], created: function () { this._instances = []; +this._pool = []; +this._limit = Infinity; +var self = this; +this._boundRenderChunk = function () { +self._renderChunk(); +}; }, detached: function () { for (var i = 0; i < this._instances.length; i++) { -this._detachRow(i); +this._detachInstance(i); } }, attached: function () { -var parentNode = Polymer.dom(this).parentNode; +var parent = Polymer.dom(Polymer.dom(this).parentNode); for (var i = 0; i < this._instances.length; i++) { -Polymer.dom(parentNode).insertBefore(this._instances[i].root, this); +this._attachInstance(i, parent); } }, ready: function () { @@ -7579,9 +8402,8 @@ this.templatize(this); } }, -_sortChanged: function () { +_sortChanged: function (sort) { var dataHost = this._getRootDataHost(); -var sort = this.sort; this._sortFn = sort && (typeof sort == 'function' ? sort : function () { return dataHost[sort].apply(dataHost, arguments); }); @@ -7590,9 +8412,8 @@ this._debounceTemplate(this._render); } }, -_filterChanged: function () { +_filterChanged: function (filter) { var dataHost = this._getRootDataHost(); -var filter = this.filter; this._filterFn = filter && (typeof filter == 'function' ? filter : function () { return dataHost[filter].apply(dataHost, arguments); }); @@ -7601,6 +8422,32 @@ this._debounceTemplate(this._render); } }, +_computeFrameTime: function (rate) { +return Math.ceil(1000 / rate); +}, +_initializeChunking: function () { +if (this.initialCount) { +this._limit = this.initialCount; +this._chunkCount = this.initialCount; +this._lastChunkTime = performance.now(); +} +}, +_tryRenderChunk: function () { +if (this.items && this._limit < this.items.length) { +this.debounce('renderChunk', this._requestRenderChunk); +} +}, +_requestRenderChunk: function () { +requestAnimationFrame(this._boundRenderChunk); +}, +_renderChunk: function () { +var currChunkTime = performance.now(); +var ratio = this._targetFrameTime / (currChunkTime - this._lastChunkTime); +this._chunkCount = Math.round(this._chunkCount * ratio) || 1; +this._limit += this._chunkCount; +this._lastChunkTime = currChunkTime; +this._debounceTemplate(this._render); +}, _observeChanged: function () { this._observePaths = this.observe && this.observe.replace('.*', '.').split(' '); }, @@ -7616,6 +8463,7 @@ this._keySplices = []; this._indexSplices = []; this._needFullRefresh = true; +this._initializeChunking(); this._debounceTemplate(this._render); } else if (change.path == 'items.splices') { this._keySplices = this._keySplices.concat(change.value.keySplices); @@ -7654,7 +8502,7 @@ if (this._needFullRefresh) { this._applyFullRefresh(); this._needFullRefresh = false; -} else { +} else if (this._keySplices.length) { if (this._sortFn) { this._applySplicesUserSort(this._keySplices); } else { @@ -7664,16 +8512,26 @@ this._applySplicesArrayOrder(this._indexSplices); } } +} else { } this._keySplices = []; this._indexSplices = []; var keyToIdx = this._keyToInstIdx = {}; -for (var i = 0; i < this._instances.length; i++) { +for (var i = this._instances.length - 1; i >= 0; i--) { var inst = this._instances[i]; +if (inst.isPlaceholder && i < this._limit) { +inst = this._insertInstance(i, inst.__key__); +} else if (!inst.isPlaceholder && i >= this._limit) { +inst = this._downgradeInstance(i, inst.__key__); +} keyToIdx[inst.__key__] = i; +if (!inst.isPlaceholder) { inst.__setProperty(this.indexAs, i, true); } +} +this._pool.length = 0; this.fire('dom-change'); +this._tryRenderChunk(); }, _applyFullRefresh: function () { var c = this.collection; @@ -7689,33 +8547,34 @@ } } } +var self = this; if (this._filterFn) { keys = keys.filter(function (a) { -return this._filterFn(c.getItem(a)); -}, this); +return self._filterFn(c.getItem(a)); +}); } if (this._sortFn) { keys.sort(function (a, b) { -return this._sortFn(c.getItem(a), c.getItem(b)); -}.bind(this)); +return self._sortFn(c.getItem(a), c.getItem(b)); +}); } for (var i = 0; i < keys.length; i++) { var key = keys[i]; var inst = this._instances[i]; if (inst) { -inst.__setProperty('__key__', key, true); +inst.__key__ = key; +if (!inst.isPlaceholder && i < this._limit) { inst.__setProperty(this.as, c.getItem(key), true); +} +} else if (i < this._limit) { +this._insertInstance(i, key); } else { -this._instances.push(this._insertRow(i, key)); +this._insertPlaceholder(i, key); } } -for (; i < this._instances.length; i++) { -this._detachRow(i); +for (var j = this._instances.length - 1; j >= i; j--) { +this._detachAndRemoveInstance(j); } -this._instances.splice(keys.length, this._instances.length - keys.length); -}, -_keySort: function (a, b) { -return this.collection.getKey(a) - this.collection.getKey(b); }, _numericSort: function (a, b) { return a - b; @@ -7724,18 +8583,16 @@ var c = this.collection; var instances = this._instances; var keyMap = {}; -var pool = []; -var sortFn = this._sortFn || this._keySort.bind(this); -splices.forEach(function (s) { -for (var i = 0; i < s.removed.length; i++) { -var key = s.removed[i]; +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { +for (var j = 0; j < s.removed.length; j++) { +var key = s.removed[j]; keyMap[key] = keyMap[key] ? null : -1; } -for (var i = 0; i < s.added.length; i++) { -var key = s.added[i]; +for (var j = 0; j < s.added.length; j++) { +var key = s.added[j]; keyMap[key] = keyMap[key] ? null : 1; } -}, this); +} var removedIdxs = []; var addedKeys = []; for (var key in keyMap) { @@ -7751,36 +8608,35 @@ for (var i = removedIdxs.length - 1; i >= 0; i--) { var idx = removedIdxs[i]; if (idx !== undefined) { -pool.push(this._detachRow(idx)); -instances.splice(idx, 1); +this._detachAndRemoveInstance(idx); } } } +var self = this; if (addedKeys.length) { if (this._filterFn) { addedKeys = addedKeys.filter(function (a) { -return this._filterFn(c.getItem(a)); -}, this); +return self._filterFn(c.getItem(a)); +}); } addedKeys.sort(function (a, b) { -return this._sortFn(c.getItem(a), c.getItem(b)); -}.bind(this)); +return self._sortFn(c.getItem(a), c.getItem(b)); +}); var start = 0; for (var i = 0; i < addedKeys.length; i++) { -start = this._insertRowUserSort(start, addedKeys[i], pool); +start = this._insertRowUserSort(start, addedKeys[i]); } } }, -_insertRowUserSort: function (start, key, pool) { +_insertRowUserSort: function (start, key) { var c = this.collection; var item = c.getItem(key); var end = this._instances.length - 1; var idx = -1; -var sortFn = this._sortFn || this._keySort.bind(this); while (start <= end) { var mid = start + end >> 1; var midKey = this._instances[mid].__key__; -var cmp = sortFn(c.getItem(midKey), item); +var cmp = this._sortFn(c.getItem(midKey), item); if (cmp < 0) { start = mid + 1; } else if (cmp > 0) { @@ -7793,65 +8649,80 @@ if (idx < 0) { idx = end + 1; } -this._instances.splice(idx, 0, this._insertRow(idx, key, pool)); +this._insertPlaceholder(idx, key); return idx; }, _applySplicesArrayOrder: function (splices) { -var pool = []; var c = this.collection; -splices.forEach(function (s) { -for (var i = 0; i < s.removed.length; i++) { -var inst = this._detachRow(s.index + i); -if (!inst.isPlaceholder) { -pool.push(inst); +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { +for (var j = 0; j < s.removed.length; j++) { +this._detachAndRemoveInstance(s.index); } -} -this._instances.splice(s.index, s.removed.length); -for (var i = 0; i < s.addedKeys.length; i++) { -var inst = { -isPlaceholder: true, -key: s.addedKeys[i] -}; -this._instances.splice(s.index + i, 0, inst); -} -}, this); -for (var i = this._instances.length - 1; i >= 0; i--) { -var inst = this._instances[i]; -if (inst.isPlaceholder) { -this._instances[i] = this._insertRow(i, inst.key, pool, true); +for (var j = 0; j < s.addedKeys.length; j++) { +this._insertPlaceholder(s.index + j, s.addedKeys[j]); } } }, -_detachRow: function (idx) { +_detachInstance: function (idx) { var inst = this._instances[idx]; if (!inst.isPlaceholder) { -var parentNode = Polymer.dom(this).parentNode; for (var i = 0; i < inst._children.length; i++) { var el = inst._children[i]; Polymer.dom(inst.root).appendChild(el); } -} return inst; -}, -_insertRow: function (idx, key, pool, replace) { -var inst; -if (inst = pool && pool.pop()) { -inst.__setProperty(this.as, this.collection.getItem(key), true); -inst.__setProperty('__key__', key, true); -} else { -inst = this._generateRow(idx, key); } -var beforeRow = this._instances[replace ? idx + 1 : idx]; -var beforeNode = beforeRow ? beforeRow._children[0] : this; -var parentNode = Polymer.dom(this).parentNode; -Polymer.dom(parentNode).insertBefore(inst.root, beforeNode); -return inst; }, -_generateRow: function (idx, key) { +_attachInstance: function (idx, parent) { +var inst = this._instances[idx]; +if (!inst.isPlaceholder) { +parent.insertBefore(inst.root, this); +} +}, +_detachAndRemoveInstance: function (idx) { +var inst = this._detachInstance(idx); +if (inst) { +this._pool.push(inst); +} +this._instances.splice(idx, 1); +}, +_insertPlaceholder: function (idx, key) { +this._instances.splice(idx, 0, { +isPlaceholder: true, +__key__: key +}); +}, +_stampInstance: function (idx, key) { var model = { __key__: key }; model[this.as] = this.collection.getItem(key); model[this.indexAs] = idx; -var inst = this.stamp(model); +return this.stamp(model); +}, +_insertInstance: function (idx, key) { +var inst = this._pool.pop(); +if (inst) { +inst.__setProperty(this.as, this.collection.getItem(key), true); +inst.__setProperty('__key__', key, true); +} else { +inst = this._stampInstance(idx, key); +} +var beforeRow = this._instances[idx + 1]; +var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this; +var parentNode = Polymer.dom(this).parentNode; +Polymer.dom(parentNode).insertBefore(inst.root, beforeNode); +this._instances[idx] = inst; +return inst; +}, +_downgradeInstance: function (idx, key) { +var inst = this._detachInstance(idx); +if (inst) { +this._pool.push(inst); +} +inst = { +isPlaceholder: true, +__key__: key +}; +this._instances[idx] = inst; return inst; }, _showHideChildren: function (hidden) { @@ -7872,18 +8743,24 @@ }, _forwardInstancePath: function (inst, path, value) { if (path.indexOf(this.as + '.') === 0) { -this.notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value); +this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value); } }, _forwardParentProp: function (prop, value) { -this._instances.forEach(function (inst) { +var i$ = this._instances; +for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) { +if (!inst.isPlaceholder) { inst.__setProperty(prop, value, true); -}, this); +} +} }, _forwardParentPath: function (path, value) { -this._instances.forEach(function (inst) { -inst.notifyPath(path, value, true); -}, this); +var i$ = this._instances; +for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) { +if (!inst.isPlaceholder) { +inst._notifyPath(path, value, true); +} +} }, _forwardItemPath: function (path, value) { if (this._keyToInstIdx) { @@ -7891,10 +8768,10 @@ var key = path.substring(0, dot < 0 ? path.length : dot); var idx = this._keyToInstIdx[key]; var inst = this._instances[idx]; -if (inst) { +if (inst && !inst.isPlaceholder) { if (dot >= 0) { path = this.as + '.' + path.substring(dot + 1); -inst.notifyPath(path, value, true); +inst._notifyPath(path, value, true); } else { inst.__setProperty(this.as, value, true); } @@ -7916,6 +8793,7 @@ }); Polymer({ is: 'array-selector', +_template: null, properties: { items: { type: Array, @@ -7946,6 +8824,7 @@ } } else { this.unlinkPaths('selected'); +this.unlinkPaths('selectedItem'); } if (this.multi) { if (!this.selected || this.selected.length) { @@ -8007,6 +8886,7 @@ Polymer({ is: 'dom-if', extends: 'template', +_template: null, properties: { 'if': { type: Boolean, @@ -8054,20 +8934,23 @@ }, _ensureInstance: function () { if (!this._instance) { +var parentNode = Polymer.dom(this).parentNode; +if (parentNode) { +var parent = Polymer.dom(parentNode); this._instance = this.stamp(); var root = this._instance.root; -var parent = Polymer.dom(Polymer.dom(this).parentNode); parent.insertBefore(root, this); } +} }, _teardownInstance: function () { if (this._instance) { -var c = this._instance._children; -if (c) { -var parent = Polymer.dom(Polymer.dom(c[0]).parentNode); -c.forEach(function (n) { +var c$ = this._instance._children; +if (c$) { +var parent = Polymer.dom(Polymer.dom(c$[0]).parentNode); +for (var i = 0, n; i < c$.length && (n = c$[i]); i++) { parent.removeChild(n); -}); +} } this._instance = null; } @@ -8085,15 +8968,19 @@ }, _forwardParentPath: function (path, value) { if (this._instance) { -this._instance.notifyPath(path, value, true); +this._instance._notifyPath(path, value, true); } } }); Polymer({ is: 'dom-bind', extends: 'template', +_template: null, created: function () { -Polymer.RenderStatus.whenReady(this._markImportsReady.bind(this)); +var self = this; +Polymer.RenderStatus.whenReady(function () { +self._markImportsReady(); +}); }, _ensureReady: function () { if (!this._readied) { @@ -8132,7 +9019,10 @@ for (var prop in this._propertyEffects) { config[prop] = this[prop]; } -this._setupConfigure = this._setupConfigure.bind(this, config); +var setupConfigure = this._setupConfigure; +this._setupConfigure = function () { +setupConfigure.call(this, config); +}; }, attached: function () { if (this._importsReady) { @@ -8151,8 +9041,9 @@ this._prepBehaviors(); this._prepConfigure(); this._prepBindings(); +this._prepPropertyInfo(); Polymer.Base._initFeatures.call(this); -this._children = Array.prototype.slice.call(this.root.childNodes); +this._children = Polymer.DomApi.arrayCopyChildNodes(this.root); } this._insertChildren(); this.fire('dom-change'); @@ -8340,7 +9231,7 @@ var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; - var DEFAULT_PHYSICAL_COUNT = 20; + var DEFAULT_PHYSICAL_COUNT = 3; var MAX_PHYSICAL_COUNT = 500; Polymer({ @@ -8523,7 +9414,7 @@ _scrollHeight: 0, /** - * The size of the viewport + * The height of the list. This is referred as the viewport in the context of list. */ _viewportSize: 0, @@ -8559,6 +9450,16 @@ _itemsRendered: false, /** + * The page that is currently rendered. + */ + _lastPage: null, + + /** + * The max number of pages to render. One page is equivalent to the height of the list. + */ + _maxPages: 3, + + /** * The bottom of the physical content. */ get _physicalBottom() { @@ -8566,6 +9467,13 @@ }, /** + * The bottom of the scroll. + */ + get _scrollBottom() { + return this._scrollPosition + this._viewportSize; + }, + + /** * The n-th item rendered in the last physical item. */ get _virtualEnd() { @@ -8623,7 +9531,7 @@ * to a viewport of physical items above and below the user's viewport. */ get _optPhysicalSize() { - return this._viewportSize * 3; + return this._viewportSize * this._maxPages; }, /** @@ -8720,19 +9628,13 @@ * items in the viewport and recycle tiles as needed. */ _refresh: function() { - var SCROLL_DIRECTION_UP = -1; - var SCROLL_DIRECTION_DOWN = 1; - var SCROLL_DIRECTION_NONE = 0; - // clamp the `scrollTop` value // IE 10|11 scrollTop may go above `_maxScrollTop` // iOS `scrollTop` may go below 0 and above `_maxScrollTop` var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scroller.scrollTop)); - - var tileHeight, kth, recycledTileSet; + var tileHeight, tileTop, kth, recycledTileSet, scrollBottom, physicalBottom; var ratio = this._ratio; var delta = scrollTop - this._scrollPosition; - var direction = SCROLL_DIRECTION_NONE; var recycledTiles = 0; var hiddenContentSize = this._hiddenContentSize; var currentRatio = ratio; @@ -8744,10 +9646,12 @@ // clear cached visible index this._firstVisibleIndexVal = null; + scrollBottom = this._scrollBottom; + physicalBottom = this._physicalBottom; + // random access if (Math.abs(delta) > this._physicalSize) { this._physicalTop += delta; - direction = SCROLL_DIRECTION_NONE; recycledTiles = Math.round(delta / this._physicalAverage); } // scroll up @@ -8755,7 +9659,6 @@ var topSpace = scrollTop - this._physicalTop; var virtualStart = this._virtualStart; - direction = SCROLL_DIRECTION_UP; recycledTileSet = []; kth = this._physicalEnd; @@ -8768,12 +9671,14 @@ // recycle less physical items than the total recycledTiles < this._physicalCount && // ensure that these recycled tiles are needed - virtualStart - recycledTiles > 0 + virtualStart - recycledTiles > 0 && + // ensure that the tile is not visible + physicalBottom - this._physicalSizes[kth] > scrollBottom ) { - tileHeight = this._physicalSizes[kth] || this._physicalAverage; + tileHeight = this._physicalSizes[kth]; currentRatio += tileHeight / hiddenContentSize; - + physicalBottom -= tileHeight; recycledTileSet.push(kth); recycledTiles++; kth = (kth === 0) ? this._physicalCount - 1 : kth - 1; @@ -8781,15 +9686,13 @@ movingUp = recycledTileSet; recycledTiles = -recycledTiles; - } // scroll down else if (delta > 0) { - var bottomSpace = this._physicalBottom - (scrollTop + this._viewportSize); + var bottomSpace = physicalBottom - scrollBottom; var virtualEnd = this._virtualEnd; var lastVirtualItemIndex = this._virtualCount-1; - direction = SCROLL_DIRECTION_DOWN; recycledTileSet = []; kth = this._physicalStart; @@ -8802,10 +9705,12 @@ // recycle less physical items than the total recycledTiles < this._physicalCount && // ensure that these recycled tiles are needed - virtualEnd + recycledTiles < lastVirtualItemIndex + virtualEnd + recycledTiles < lastVirtualItemIndex && + // ensure that the tile is not visible + this._physicalTop + this._physicalSizes[kth] < scrollTop ) { - tileHeight = this._physicalSizes[kth] || this._physicalAverage; + tileHeight = this._physicalSizes[kth]; currentRatio += tileHeight / hiddenContentSize; this._physicalTop += tileHeight; @@ -8815,7 +9720,14 @@ } } - if (recycledTiles !== 0) { + if (recycledTiles === 0) { + // If the list ever reach this case, the physical average is not significant enough + // to create all the items needed to cover the entire viewport. + // e.g. A few items have a height that differs from the average by serveral order of magnitude. + if (physicalBottom < scrollBottom || this._physicalTop > scrollTop) { + this.async(this._increasePool.bind(this, 1)); + } + } else { this._virtualStart = this._virtualStart + recycledTiles; this._update(recycledTileSet, movingUp); } @@ -8845,11 +9757,8 @@ // set the scroller size this._updateScrollerSize(); - // increase the pool of physical items if needed - if (this._increasePoolIfNeeded()) { - // set models to the new items - this.async(this._update); - } + // increase the pool of physical items + this._increasePoolIfNeeded(); }, /** @@ -8862,7 +9771,6 @@ for (var i = 0; i < size; i++) { var inst = this.stamp(null); - // First element child is item; Safari doesn't support children[0] // on a doc fragment physicalItems[i] = inst.root.querySelector('*'); @@ -8873,47 +9781,52 @@ }, /** - * Increases the pool size. That is, the physical items in the DOM. + * Increases the pool of physical items only if needed. * This function will allocate additional physical items - * (limited by `MAX_PHYSICAL_COUNT`) if the content size is shorter than - * `_optPhysicalSize` - * - * @return boolean + * if the physical size is shorter than `_optPhysicalSize` */ _increasePoolIfNeeded: function() { - if (this._physicalSize >= this._optPhysicalSize || this._physicalAverage === 0) { - return false; + if (this._viewportSize !== 0 && this._physicalSize < this._optPhysicalSize) { + // 0 <= `currentPage` <= `_maxPages` + var currentPage = Math.floor(this._physicalSize / this._viewportSize); + + if (currentPage === 0) { + // fill the first page + this.async(this._increasePool.bind(this, Math.round(this._physicalCount * 0.5))); + } else if (this._lastPage !== currentPage) { + // once a page is filled up, paint it and defer the next increase + requestAnimationFrame(this._increasePool.bind(this, 1)); + } else { + // fill the rest of the pages + this.async(this._increasePool.bind(this, 1)); + } + this._lastPage = currentPage; + return true; } + return false; + }, - // the estimated number of physical items that we will need to reach - // the cap established by `_optPhysicalSize`. - var missingItems = Math.round( - (this._optPhysicalSize - this._physicalSize) * 1.2 / this._physicalAverage - ); - + /** + * Increases the pool size. + */ + _increasePool: function(missingItems) { // limit the size var nextPhysicalCount = Math.min( this._physicalCount + missingItems, this._virtualCount, MAX_PHYSICAL_COUNT ); - var prevPhysicalCount = this._physicalCount; var delta = nextPhysicalCount - prevPhysicalCount; - if (delta <= 0) { - return false; + if (delta > 0) { + [].push.apply(this._physicalItems, this._createPool(delta)); + [].push.apply(this._physicalSizes, new Array(delta)); + + this._physicalCount = prevPhysicalCount + delta; + // tail call + return this._update(); } - - var newPhysicalItems = this._createPool(delta); - var emptyArray = new Array(delta); - - [].push.apply(this._physicalItems, newPhysicalItems); - [].push.apply(this._physicalSizes, emptyArray); - - this._physicalCount = prevPhysicalCount + delta; - - return true; }, /** @@ -8923,7 +9836,8 @@ _render: function() { var requiresUpdate = this._virtualCount > 0 || this._physicalCount > 0; - if (this.isAttached && !this._itemsRendered && this._isVisible && requiresUpdate) { + if (this.isAttached && !this._itemsRendered && this._isVisible && requiresUpdate) { + this._lastPage = 0; this._update(); this._itemsRendered = true; } @@ -9287,7 +10201,7 @@ var hiddenContentSize = this._hiddenContentSize; // scroll to the item as much as we can - while (currentVirtualItem !== idx && targetOffsetTop < hiddenContentSize) { + while (currentVirtualItem < idx && targetOffsetTop < hiddenContentSize) { targetOffsetTop = targetOffsetTop + this._physicalSizes[currentTopItem]; currentTopItem = (currentTopItem + 1) % this._physicalCount; currentVirtualItem++; @@ -9303,10 +10217,7 @@ this._resetScrollPosition(this._physicalTop + targetOffsetTop + 1); // increase the pool of physical items if needed - if (this._increasePoolIfNeeded()) { - // set models to the new items - this.async(this._update); - } + this._increasePoolIfNeeded(); // clear cached visible index this._firstVisibleIndexVal = null; @@ -9488,256 +10399,10 @@ })(); (function() { - 'use strict'; - - var SHADOW_WHEN_SCROLLING = 1; - var SHADOW_ALWAYS = 2; - - - var MODE_CONFIGS = { - - outerScroll: { - 'scroll': true - }, - - shadowMode: { - 'standard': SHADOW_ALWAYS, - 'waterfall': SHADOW_WHEN_SCROLLING, - 'waterfall-tall': SHADOW_WHEN_SCROLLING - }, - - tallMode: { - 'waterfall-tall': true - } - }; - - Polymer({ - - is: 'paper-header-panel', - - /** - * Fired when the content has been scrolled. `event.detail.target` returns - * the scrollable element which you can use to access scroll info such as - * `scrollTop`. - * - * <paper-header-panel on-content-scroll="scrollHandler"> - * ... - * </paper-header-panel> - * - * - * scrollHandler: function(event) { - * var scroller = event.detail.target; - * console.log(scroller.scrollTop); - * } - * - * @event content-scroll - */ - - properties: { - - /** - * Controls header and scrolling behavior. Options are - * `standard`, `seamed`, `waterfall`, `waterfall-tall`, `scroll` and - * `cover`. Default is `standard`. - * - * `standard`: The header is a step above the panel. The header will consume the - * panel at the point of entry, preventing it from passing through to the - * opposite side. - * - * `seamed`: The header is presented as seamed with the panel. - * - * `waterfall`: Similar to standard mode, but header is initially presented as - * seamed with panel, but then separates to form the step. - * - * `waterfall-tall`: The header is initially taller (`tall` class is added to - * the header). As the user scrolls, the header separates (forming an edge) - * while condensing (`tall` class is removed from the header). - * - * `scroll`: The header keeps its seam with the panel, and is pushed off screen. - * - * `cover`: The panel covers the whole `paper-header-panel` including the - * header. This allows user to style the panel in such a way that the panel is - * partially covering the header. - * - * <paper-header-panel mode="cover"> - * <paper-toolbar class="tall"> - * <core-icon-button icon="menu"></core-icon-button> - * </paper-toolbar> - * <div class="content"></div> - * </paper-header-panel> - */ - mode: { - type: String, - value: 'standard', - observer: '_modeChanged', - reflectToAttribute: true - }, - - /** - * If true, the drop-shadow is always shown no matter what mode is set to. - */ - shadow: { - type: Boolean, - value: false - }, - - /** - * The class used in waterfall-tall mode. Change this if the header - * accepts a different class for toggling height, e.g. "medium-tall" - */ - tallClass: { - type: String, - value: 'tall' - }, - - /** - * If true, the scroller is at the top - */ - atTop: { - type: Boolean, - value: true, - readOnly: true - } - }, - - observers: [ - '_computeDropShadowHidden(atTop, mode, shadow)' - ], - - ready: function() { - this.scrollHandler = this._scroll.bind(this); - this._addListener(); - - // Run `scroll` logic once to initialze class names, etc. - this._keepScrollingState(); - }, - - detached: function() { - this._removeListener(); - }, - - /** - * Returns the header element - * - * @property header - * @type Object - */ - get header() { - return Polymer.dom(this.$.headerContent).getDistributedNodes()[0]; - }, - - /** - * Returns the scrollable element. - * - * @property scroller - * @type Object - */ - get scroller() { - return this._getScrollerForMode(this.mode); - }, - - /** - * Returns true if the scroller has a visible shadow. - * - * @property visibleShadow - * @type Boolean - */ - get visibleShadow() { - return this.$.dropShadow.classList.contains('has-shadow'); - }, - - _computeDropShadowHidden: function(atTop, mode, shadow) { - - var shadowMode = MODE_CONFIGS.shadowMode[mode]; - - if (this.shadow) { - this.toggleClass('has-shadow', true, this.$.dropShadow); - - } else if (shadowMode === SHADOW_ALWAYS) { - this.toggleClass('has-shadow', true, this.$.dropShadow); - - } else if (shadowMode === SHADOW_WHEN_SCROLLING && !atTop) { - this.toggleClass('has-shadow', true, this.$.dropShadow); - - } else { - this.toggleClass('has-shadow', false, this.$.dropShadow); - - } - }, - - _computeMainContainerClass: function(mode) { - // TODO: It will be useful to have a utility for classes - // e.g. Polymer.Utils.classes({ foo: true }); - - var classes = {}; - - classes['flex'] = mode !== 'cover'; - - return Object.keys(classes).filter( - function(className) { - return classes[className]; - }).join(' '); - }, - - _addListener: function() { - this.scroller.addEventListener('scroll', this.scrollHandler, false); - }, - - _removeListener: function() { - this.scroller.removeEventListener('scroll', this.scrollHandler); - }, - - _modeChanged: function(newMode, oldMode) { - var configs = MODE_CONFIGS; - var header = this.header; - var animateDuration = 200; - - if (header) { - // in tallMode it may add tallClass to the header; so do the cleanup - // when mode is changed from tallMode to not tallMode - if (configs.tallMode[oldMode] && !configs.tallMode[newMode]) { - header.classList.remove(this.tallClass); - this.async(function() { - header.classList.remove('animate'); - }, animateDuration); - } else { - header.classList.toggle('animate', configs.tallMode[newMode]); - } - } - this._keepScrollingState(); - }, - - _keepScrollingState: function() { - var main = this.scroller; - var header = this.header; - - this._setAtTop(main.scrollTop === 0); - - if (header && this.tallClass && MODE_CONFIGS.tallMode[this.mode]) { - this.toggleClass(this.tallClass, this.atTop || - header.classList.contains(this.tallClass) && - main.scrollHeight < this.offsetHeight, header); - } - }, - - _scroll: function() { - this._keepScrollingState(); - this.fire('content-scroll', {target: this.scroller}, {bubbles: false}); - }, - - _getScrollerForMode: function(mode) { - return MODE_CONFIGS.outerScroll[mode] ? - this : this.$.mainContainer; - } - - }); - - })(); -(function() { - // monostate data var metaDatas = {}; var metaArrays = {}; + var singleton = null; Polymer.IronMeta = Polymer({ @@ -9790,9 +10455,15 @@ }, + hostAttributes: { + hidden: true + }, + /** * Only runs if someone invokes the factory/constructor directly * e.g. `new Polymer.IronMeta()` + * + * @param {{type: (string|undefined), key: (string|undefined), value}=} config */ factoryImpl: function(config) { if (config) { @@ -9884,6 +10555,13 @@ }); + Polymer.IronMeta.getIronMeta = function getIronMeta() { + if (singleton === null) { + singleton = new Polymer.IronMeta(); + } + return singleton; + }; + /** `iron-meta-query` can be used to access infomation stored in `iron-meta`. @@ -9950,6 +10628,8 @@ /** * Actually a factory method, not a true constructor. Only runs if * someone invokes it directly (via `new Polymer.IronMeta()`); + * + * @param {{type: (string|undefined), key: (string|undefined)}=} config */ factoryImpl: function(config) { if (config) { @@ -10086,9 +10766,9 @@ * `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. + * 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: * @@ -10096,8 +10776,8 @@ * <svg> * <defs> * <g id="shape"> - * <rect x="50" y="50" width="50" height="50" /> - * <circle cx="50" cy="50" r="50" /> + * <rect x="12" y="0" width="12" height="24" /> + * <circle cx="12" cy="12" r="12" /> * </g> * </defs> * </svg> @@ -10113,18 +10793,15 @@ * * @element iron-iconset-svg * @demo demo/index.html + * @implements {Polymer.Iconset} */ Polymer({ - is: 'iron-iconset-svg', properties: { /** * The name of the iconset. - * - * @attribute name - * @type string */ name: { type: String, @@ -10133,10 +10810,6 @@ /** * The size of an individual icon. Note that icons must be square. - * - * @attribute iconSize - * @type number - * @default 24 */ size: { type: Number, @@ -10145,6 +10818,10 @@ }, + attached: function() { + this.style.display = 'none'; + }, + /** * Construct an array of all icon names in this iconset. * @@ -10166,7 +10843,7 @@ * @method applyIcon * @param {Element} element Element to which the icon is applied. * @param {string} iconName Name of the icon to apply. - * @return {Element} The svg element which renders the icon. + * @return {?Element} The svg element which renders the icon. */ applyIcon: function(element, iconName) { // insert svg element into shadow root, if it exists @@ -10506,6 +11183,15 @@ } }, + /** + * If true, this property will cause the implementing element to + * automatically stop propagation on any handled KeyboardEvents. + */ + stopKeyboardEventPropagation: { + type: Boolean, + value: false + }, + _boundKeyHandlers: { type: Array, value: function() { @@ -10649,6 +11335,10 @@ }, _onKeyBindingEvent: function(keyBindings, event) { + if (this.stopKeyboardEventPropagation) { + event.stopPropagation(); + } + keyBindings.forEach(function(keyBinding) { var keyCombo = keyBinding[0]; var handlerName = keyBinding[1]; @@ -10662,10 +11352,14 @@ _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { var detail = Object.create(keyCombo); detail.keyboardEvent = keyboardEvent; - - this[handlerName].call(this, new CustomEvent(keyCombo.event, { - detail: detail - })); + var event = new CustomEvent(keyCombo.event, { + detail: detail, + cancelable: true + }); + this[handlerName].call(this, event); + if (event.defaultPrevented) { + keyboardEvent.preventDefault(); + } } }; })(); @@ -10729,9 +11423,8 @@ // handled). In either case, we can disregard `event.path`. if (event.target === this) { - var focused = event.type === 'focus'; - this._setFocused(focused); - } else if (!this.shadowRoot) { + this._setFocused(event.type === 'focus'); + } else if (!this.shadowRoot && !this.isLightDescendant(event.target)) { this.fire(event.type, {sourceEvent: event}, { node: this, bubbles: event.bubbles, @@ -10882,14 +11575,35 @@ this._setPressed(false); }, + /** + * @param {!KeyboardEvent} event . + */ _spaceKeyDownHandler: function(event) { var keyboardEvent = event.detail.keyboardEvent; + var target = Polymer.dom(keyboardEvent).localTarget; + + // Ignore the event if this is coming from a focused light child, since that + // element will deal with it. + if (this.isLightDescendant(target)) + return; + keyboardEvent.preventDefault(); keyboardEvent.stopImmediatePropagation(); this._setPressed(true); }, - _spaceKeyUpHandler: function() { + /** + * @param {!KeyboardEvent} event . + */ + _spaceKeyUpHandler: function(event) { + var keyboardEvent = event.detail.keyboardEvent; + var target = Polymer.dom(keyboardEvent).localTarget; + + // Ignore the event if this is coming from a focused light child, since that + // element will deal with it. + if (this.isLightDescendant(target)) + return; + if (this.pressed) { this._asyncClick(); } @@ -11350,10 +12064,6 @@ } }, - observers: [ - '_noinkChanged(noink, isAttached)' - ], - get target () { var ownerRoot = Polymer.dom(this).getOwnerRoot(); var target; @@ -11374,6 +12084,10 @@ }, attached: function() { + // Set up a11yKeysBehavior to listen to key events on the target, + // so that space and enter activate the ripple even if the target doesn't + // handle key events. The key handlers deal with `noink` themselves. + this.keyEventTarget = this.target; this.listen(this.target, 'up', 'uiUpAction'); this.listen(this.target, 'down', 'uiDownAction'); }, @@ -11543,12 +12257,6 @@ } else { this.upAction(); } - }, - - _noinkChanged: function(noink, attached) { - if (attached) { - this.keyEventTarget = noink ? this : this.target; - } } }); })(); @@ -11605,10 +12313,10 @@ /** * Ensures this element contains a ripple effect. For startup efficiency * the ripple effect is dynamically on demand when needed. - * @param {!Event=} opt_triggeringEvent (optional) event that triggered the + * @param {!Event=} optTriggeringEvent (optional) event that triggered the * ripple. */ - ensureRipple: function(opt_triggeringEvent) { + ensureRipple: function(optTriggeringEvent) { if (!this.hasRipple()) { this._ripple = this._createRipple(); this._ripple.noink = this.noink; @@ -11616,12 +12324,14 @@ if (rippleContainer) { Polymer.dom(rippleContainer).appendChild(this._ripple); } - var domContainer = rippleContainer === this.shadyRoot ? this : - rippleContainer; - if (opt_triggeringEvent) { - var target = opt_triggeringEvent.target; - if (domContainer.contains(/** @type {Node} */(target))) { - this._ripple.uiDownAction(opt_triggeringEvent); + if (optTriggeringEvent) { + // Check if the event happened inside of the ripple container + // Fall back to host instead of the root because distributed text + // nodes are not valid event targets + var domContainer = Polymer.dom(this._rippleContainer || this); + var target = Polymer.dom(optTriggeringEvent).rootTarget; + if (domContainer.deepContains( /** @type {Node} */(target))) { + this._ripple.uiDownAction(optTriggeringEvent); } } } @@ -11666,7 +12376,7 @@ /** * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has keyboard focus. * - * @polymerBehavior Polymer.PaperInkyFocusBehaviorImpl + * @polymerBehavior Polymer.PaperInkyFocusBehavior */ Polymer.PaperInkyFocusBehaviorImpl = { @@ -11704,7 +12414,6 @@ is: 'paper-material', properties: { - /** * The z-depth of this element, from 0-5. Setting to 0 will remove the * shadow, and each increasing number greater than 0 will be "deeper" @@ -11846,11 +12555,11 @@ } } }); -/** +/** * `iron-range-behavior` provides the behavior for something with a minimum to maximum range. * * @demo demo/index.html - * @polymerBehavior + * @polymerBehavior */ Polymer.IronRangeBehavior = { @@ -11919,7 +12628,7 @@ _calcStep: function(value) { /** * if we calculate the step using - * `Math.round(value / step) * step` we may hit a precision point issue + * `Math.round(value / step) * step` we may hit a precision point issue * eg. 0.1 * 0.2 = 0.020000000000000004 * http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html * @@ -11927,7 +12636,8 @@ */ // polymer/issues/2493 value = parseFloat(value); - return this.step ? (Math.round((value + this.min) / this.step) / (1 / this.step)) - this.min : value; + return this.step ? (Math.round((value + this.min) / this.step) - + (this.min / this.step)) / (1 / this.step) : value; }, _validateValue: function() { @@ -12378,17 +13088,25 @@ Item: Item, }; }); +/** @polymerBehavior Polymer.PaperItemBehavior */ + Polymer.PaperItemBehaviorImpl = { + hostAttributes: { + role: 'option', + tabindex: '0' + } + }; + + /** @polymerBehavior */ + Polymer.PaperItemBehavior = [ + Polymer.IronControlState, + Polymer.IronButtonState, + Polymer.PaperItemBehaviorImpl + ]; Polymer({ is: 'paper-item', - hostAttributes: { - role: 'listitem', - tabindex: '0' - }, - behaviors: [ - Polymer.IronControlState, - Polymer.IronButtonState + Polymer.PaperItemBehavior ] }); /** @@ -12542,6 +13260,8 @@ /** * Returns the currently selected item. + * + * @type {?Object} */ selectedItem: { type: Object, @@ -12583,10 +13303,20 @@ }, /** + * The list of items from which a selection can be made. + */ + items: { + type: Array, + readOnly: true, + value: function() { + return []; + } + }, + + /** * The set of excluded elements where the key is the `localName` * of the element that will be ignored from the item list. * - * @type {object} * @default {template: 1} */ _excludedLocalNames: { @@ -12606,15 +13336,12 @@ created: function() { this._bindFilterItem = this._filterItem.bind(this); this._selection = new Polymer.IronSelection(this._applySelection.bind(this)); - // TODO(cdata): When polymer/polymer#2535 lands, we do not need to do this - // book keeping anymore: - this.__listeningForActivate = false; }, attached: function() { this._observer = this._observeItems(this); - this._contentObserver = this._observeContent(this); - if (!this.selectedItem && this.selected) { + this._updateItems(); + if (!this._shouldUpdateSelection) { this._updateSelected(this.attrForSelected,this.selected) } this._addListener(this.activateEvent); @@ -12622,26 +13349,12 @@ detached: function() { if (this._observer) { - this._observer.disconnect(); - } - if (this._contentObserver) { - this._contentObserver.disconnect(); + Polymer.dom(this).unobserveNodes(this._observer); } 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 @@ -12683,18 +13396,16 @@ this.selected = this._indexToValue(index); }, - _addListener: function(eventName) { - if (!this.isAttached || this.__listeningForActivate) { - return; - } + get _shouldUpdateSelection() { + return this.selected != null; + }, - this.__listeningForActivate = true; + _addListener: function(eventName) { this.listen(this, eventName, '_activateHandler'); }, _removeListener: function(eventName) { this.unlisten(this, eventName, '_activateHandler'); - this.__listeningForActivate = false; }, _activateEventChanged: function(eventName, old) { @@ -12702,6 +13413,12 @@ this._addListener(eventName); }, + _updateItems: function() { + var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*'); + nodes = Array.prototype.filter.call(nodes, this._bindFilterItem); + this._setItems(nodes); + }, + _updateSelected: function() { this._selectSelected(this.selected); }, @@ -12760,18 +13477,9 @@ 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.domHost); - } - }, - // observe items change under the given node. _observeItems: function(node) { - // TODO(cdata): Update this when we get distributed children changed. - var observer = new MutationObserver(function(mutations) { + return Polymer.dom(node).observeNodes(function(mutations) { // Let other interested parties know about the change so that // we don't have to recreate mutation observers everywher. this.fire('iron-items-changed', mutations, { @@ -12779,15 +13487,12 @@ cancelable: false }); - if (this.selected != null) { + this._updateItems(); + + if (this._shouldUpdateSelection) { this._updateSelected(); } - }.bind(this)); - observer.observe(node, { - childList: true, - subtree: true }); - return observer; }, _activateHandler: function(e) { @@ -12872,6 +13577,11 @@ this._selection.multi = multi; }, + get _shouldUpdateSelection() { + return this.selected != null || + (this.selectedValues != null && this.selectedValues.length); + }, + _updateSelected: function() { if (this.multi) { this._selectMulti(this.selectedValues); @@ -13209,18 +13919,14 @@ Polymer.IronMenuBehaviorImpl ]; (function() { + Polymer({ + is: 'paper-menu', - Polymer({ - - is: 'paper-menu', - - behaviors: [ - Polymer.IronMenuBehavior - ] - - }); - -})(); + behaviors: [ + Polymer.IronMenuBehavior + ] + }); + })(); /** Polymer.IronFitBehavior fits an element in another element using `max-height` and `max-width`, and optionally centers it in the window or another element. @@ -13416,6 +14122,10 @@ if (!this._fitInfo.positionedBy.horizontally) { this.style.left = '0px'; } + if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy.horizontally) { + // need position:fixed to properly size the element + this.style.position = 'fixed'; + } // need border-box for margin/padding this.sizingTarget.style.boxSizing = 'border-box'; // constrain the width and height if not already set @@ -13461,60 +14171,74 @@ } }; -Polymer.IronOverlayManager = (function() { +Polymer.IronOverlayManager = { - var overlays = []; - var DEFAULT_Z = 10; - var backdrops = []; + _overlays: [], + + // iframes have a default z-index of 100, so this default should be at least + // that. + _minimumZ: 101, + + _backdrops: [], + + _applyOverlayZ: function(overlay, aboveZ) { + this._setZ(overlay, aboveZ + 2); + }, + + _setZ: function(element, z) { + element.style.zIndex = z; + }, // track overlays for z-index and focus managemant - function addOverlay(overlay) { - var z0 = currentOverlayZ(); - overlays.push(overlay); - var z1 = currentOverlayZ(); - if (z1 <= z0) { - applyOverlayZ(overlay, z0); + addOverlay: function(overlay) { + var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ); + this._overlays.push(overlay); + var newZ = this.currentOverlayZ(); + if (newZ <= minimumZ) { + this._applyOverlayZ(overlay, minimumZ); } - } + }, - function removeOverlay(overlay) { - var i = overlays.indexOf(overlay); + removeOverlay: function(overlay) { + var i = this._overlays.indexOf(overlay); if (i >= 0) { - overlays.splice(i, 1); - setZ(overlay, ''); + this._overlays.splice(i, 1); + this._setZ(overlay, ''); } - } + }, - function applyOverlayZ(overlay, aboveZ) { - setZ(overlay, aboveZ + 2); - } - - function setZ(element, z) { - element.style.zIndex = z; - } - - function currentOverlay() { - var i = overlays.length - 1; - while (overlays[i] && !overlays[i].opened) { + currentOverlay: function() { + var i = this._overlays.length - 1; + while (this._overlays[i] && !this._overlays[i].opened) { --i; } - return overlays[i]; - } + return this._overlays[i]; + }, - function currentOverlayZ() { - var z; - var current = currentOverlay(); + currentOverlayZ: function() { + var z = this._minimumZ; + var current = this.currentOverlay(); if (current) { var z1 = window.getComputedStyle(current).zIndex; if (!isNaN(z1)) { z = Number(z1); } } - return z || DEFAULT_Z; - } + return z; + }, - function focusOverlay() { - var current = currentOverlay(); + /** + * Ensures that the minimum z-index of new overlays is at least `minimumZ`. + * This does not effect the z-index of any existing overlays. + * + * @param {number} minimumZ + */ + ensureMinimumZ: function(minimumZ) { + this._minimumZ = Math.max(this._minimumZ, minimumZ); + }, + + focusOverlay: function() { + var current = this.currentOverlay(); // We have to be careful to focus the next overlay _after_ any current // transitions are complete (due to the state being toggled prior to the // transition). Otherwise, we risk infinite recursion when a transitioning @@ -13526,36 +14250,26 @@ if (current && !current.transitioning) { current._applyFocus(); } - } + }, - function trackBackdrop(element) { + trackBackdrop: function(element) { // backdrops contains the overlays with a backdrop that are currently // visible if (element.opened) { - backdrops.push(element); + this._backdrops.push(element); } else { - var index = backdrops.indexOf(element); + var index = this._backdrops.indexOf(element); if (index >= 0) { - backdrops.splice(index, 1); + this._backdrops.splice(index, 1); } } + }, + + getBackdrops: function() { + return this._backdrops; } - function getBackdrops() { - return backdrops; - } - - return { - addOverlay: addOverlay, - removeOverlay: removeOverlay, - currentOverlay: currentOverlay, - currentOverlayZ: currentOverlayZ, - focusOverlay: focusOverlay, - trackBackdrop: trackBackdrop, - getBackdrops: getBackdrops - }; - - })(); + }; (function() { Polymer({ @@ -14042,6 +14756,12 @@ */ /** + * Fired when the `iron-overlay` is canceled, but before it is closed. + * Cancel the event to prevent the `iron-overlay` from closing. + * @event iron-overlay-canceled + */ + +/** * Fired after the `iron-overlay` closes. * @event iron-overlay-closed * @param {{canceled: (boolean|undefined)}} set to the `closingReason` attribute @@ -15407,7 +16127,20 @@ } }); /** - * Use `Polymer.IronValidatableBehavior` to implement an element that validates user input. + * `Use Polymer.IronValidatableBehavior` to implement an element that validates user input. + * Use the related `Polymer.IronValidatorBehavior` to add custom validation logic to an iron-input. + * + * By default, an `<iron-form>` element validates its fields when the user presses the submit button. + * To validate a form imperatively, call the form's `validate()` method, which in turn will + * call `validate()` on all its children. By using `Polymer.IronValidatableBehavior`, your + * custom element will get a public `validate()`, which + * will return the validity of the element, and a corresponding `invalid` attribute, + * which can be used for styling. + * + * To implement the custom validation logic of your element, you must override + * the protected `_getValidity()` method of this behaviour, rather than `validate()`. + * See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/simple-element.html) + * for an example. * * ### Accessibility * @@ -15577,7 +16310,8 @@ * Regular expression to match valid input characters. */ allowedPattern: { - type: String + type: String, + observer: "_allowedPatternChanged" }, _previousValidInput: { @@ -15628,6 +16362,11 @@ this.fire('bind-value-changed', {value: this.bindValue}); }, + _allowedPatternChanged: function() { + // Force to prevent invalid input when an `allowed-pattern` is set + this.preventInvalidInput = this.allowedPattern ? true : false; + }, + _onInput: function() { // Need to validate each of the characters pasted if they haven't // been validated inside `_onKeypress` already. @@ -15974,21 +16713,19 @@ if (alwaysFloatLabel || _inputHasContent) { cls += ' label-is-floating'; + // If the label is floating, ignore any offsets that may have been + // applied from a prefix element. + this.$.labelAndInputContainer.style.position = 'static'; + if (invalid) { cls += ' is-invalid'; } else if (focused) { cls += " label-is-highlighted"; } - // The label might have a horizontal offset if a prefix element exists - // which needs to be undone when displayed as a floating label. - if (Polymer.dom(this.$.prefix).getDistributedNodes().length > 0 && - label && label.offsetParent) { - label.style.left = -label.offsetParent.offsetLeft + 'px'; - } } else { // When the label is not floating, it should overlap the input element. if (label) { - label.style.left = 0; + this.$.labelAndInputContainer.style.position = 'relative'; } } } else { @@ -16209,6 +16946,10 @@ }, }, + hostAttributes: { + loading: true, + }, + /** * @param {Event} e * @private @@ -16291,7 +17032,7 @@ if (loadTimeData.getBoolean('allowDeletingHistory')) this.$.toolbar.downloadsShowing = this.hasDownloads_; - this.$.panel.classList.remove('loading'); + this.removeAttribute('loading'); }, /**
diff --git a/chrome/browser/resources/md_downloads/manager.css b/chrome/browser/resources/md_downloads/manager.css index c7f50d1..5d08910 100644 --- a/chrome/browser/resources/md_downloads/manager.css +++ b/chrome/browser/resources/md_downloads/manager.css
@@ -7,6 +7,7 @@ flex: 1 0; flex-direction: column; height: 100%; + overflow-y: overlay; } @media screen and (max-width: 1024px) { @@ -15,23 +16,13 @@ } } -#panel { - --paper-header-panel-shadow: { - display: none; - }; - --paper-header-panel-standard-container: { - display: flex; - overflow-y: overlay; - }; -} - #no-downloads, #downloads-list { flex: 1; } -.loading #no-downloads, -.loading #downloads-list { +:host([loading]) #no-downloads, +:host([loading]) #downloads-list { display: none; }
diff --git a/chrome/browser/resources/md_downloads/manager.html b/chrome/browser/resources/md_downloads/manager.html index 3f2c7e82..d1b2fa7 100644 --- a/chrome/browser/resources/md_downloads/manager.html +++ b/chrome/browser/resources/md_downloads/manager.html
@@ -4,7 +4,6 @@ <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html"> <link rel="import" href="chrome://downloads/action_service.html"> <link rel="import" href="chrome://downloads/constants.html"> <link rel="import" href="chrome://downloads/i18n_setup.html"> @@ -13,22 +12,20 @@ <dom-module id="downloads-manager"> <template> - <paper-header-panel id="panel" class="loading"> - <downloads-toolbar class="paper-header" id="toolbar"></downloads-toolbar> - <iron-list id="downloads-list" items="{{items_}}" - hidden="[[!hasDownloads_]]"> - <template> - <downloads-item data="[[item]]" hide-date="[[item.hideDate]]"> - </downloads-item> - </template> - </iron-list> - <div id="no-downloads" hidden="[[hasDownloads_]]"> - <div> - <div class="illustration"></div> - <span><!-- Text populated in Manager#updateAll_(). --></span> - </div> + <downloads-toolbar id="toolbar"></downloads-toolbar> + <iron-list id="downloads-list" items="{{items_}}" + hidden="[[!hasDownloads_]]"> + <template> + <downloads-item data="[[item]]" hide-date="[[item.hideDate]]"> + </downloads-item> + </template> + </iron-list> + <div id="no-downloads" hidden="[[hasDownloads_]]"> + <div> + <div class="illustration"></div> + <span><!-- Text populated in Manager#updateAll_(). --></span> </div> - </paper-header-panel> + </div> </template> <link rel="import" type="css" href="chrome://downloads/shared_style.css"> <link rel="import" type="css" href="chrome://downloads/manager.css">
diff --git a/chrome/browser/resources/md_downloads/manager.js b/chrome/browser/resources/md_downloads/manager.js index 21acd294..76017ac 100644 --- a/chrome/browser/resources/md_downloads/manager.js +++ b/chrome/browser/resources/md_downloads/manager.js
@@ -17,6 +17,10 @@ }, }, + hostAttributes: { + loading: true, + }, + /** * @param {Event} e * @private @@ -99,7 +103,7 @@ if (loadTimeData.getBoolean('allowDeletingHistory')) this.$.toolbar.downloadsShowing = this.hasDownloads_; - this.$.panel.classList.remove('loading'); + this.removeAttribute('loading'); }, /**
diff --git a/chrome/browser/resources/md_downloads/shared_style.css b/chrome/browser/resources/md_downloads/shared_style.css index 171fdf1f..73d304a 100644 --- a/chrome/browser/resources/md_downloads/shared_style.css +++ b/chrome/browser/resources/md_downloads/shared_style.css
@@ -6,6 +6,10 @@ --downloads-item-width: 622px; } +[hidden] { + display: none !important; +} + paper-button { font-weight: 500; margin: 0;
diff --git a/chrome/browser/resources/md_downloads/toolbar.css b/chrome/browser/resources/md_downloads/toolbar.css index ba94b688..a4767b81 100644 --- a/chrome/browser/resources/md_downloads/toolbar.css +++ b/chrome/browser/resources/md_downloads/toolbar.css
@@ -26,7 +26,7 @@ width: var(--downloads-item-width); } -:host-context(.loading) #actions { +:host-context([loading]) #actions { visibility: hidden; }
diff --git a/chrome/browser/resources/md_downloads/vulcanized.html b/chrome/browser/resources/md_downloads/vulcanized.html index 637dc280a..3e136d15 100644 --- a/chrome/browser/resources/md_downloads/vulcanized.html +++ b/chrome/browser/resources/md_downloads/vulcanized.html
@@ -1,4 +1,4 @@ -<!DOCTYPE html><html i18n-values="dir:textdirection;lang:language"><head><script src="crisper.js" defer=""></script><!-- +<!DOCTYPE html><html i18n-values="dir:textdirection;lang:language"><head><!-- @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 @@ -338,6 +338,11 @@ overflow: auto; }; + --layout-fullbleed: { + margin: 0; + height: 100vh; + } + /* fixed position */ --layout-fixed-top: { @@ -373,6 +378,8 @@ </style> + + <style is="custom-style"> :root { @@ -738,14 +745,14 @@ /* opacity for dark text on a light background */ --dark-divider-opacity: 0.12; - --dark-disabled-opacity: 0.26; /* or hint text */ - --dark-secondary-opacity: 0.54; /* or icon */ + --dark-disabled-opacity: 0.38; /* or hint text or icon */ + --dark-secondary-opacity: 0.54; --dark-primary-opacity: 0.87; /* opacity for light text on a dark background */ --light-divider-opacity: 0.12; - --light-disabled-opacity: 0.3; /* or hint text */ - --light-secondary-opacity: 0.7; /* or icon */ + --light-disabled-opacity: 0.3; /* or hint text or icon */ + --light-secondary-opacity: 0.7; --light-primary-opacity: 1.0; } @@ -753,594 +760,6 @@ </style> -<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> -<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> <style is="custom-style"> :root { @@ -1368,6 +787,14 @@ } </style> + + + + + + + + <style> /* Copyright 2015 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be @@ -1426,8 +853,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + /* @apply(--paper-font-common-nowrap); */ white-space: nowrap; overflow: hidden; @@ -1443,8 +869,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + /* @apply(--paper-font-common-nowrap); */ white-space: nowrap; overflow: hidden; @@ -1460,8 +885,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + font-size: 45px; font-weight: 400; @@ -1473,8 +897,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + font-size: 34px; font-weight: 400; @@ -1486,8 +909,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + font-size: 24px; font-weight: 400; @@ -1499,8 +921,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + /* @apply(--paper-font-common-nowrap); */ white-space: nowrap; overflow: hidden; @@ -1515,8 +936,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + font-size: 16px; font-weight: 400; @@ -1562,8 +982,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + /* @apply(--paper-font-common-nowrap); */ white-space: nowrap; overflow: hidden; @@ -1578,8 +997,7 @@ /* @apply(--paper-font-common-base) */ font-family: 'Roboto', 'Noto', sans-serif; -webkit-font-smoothing: antialiased; - /* @apply(--paper-font-common-expensive-kerning); */ - text-rendering: optimizeLegibility; + /* @apply(--paper-font-common-nowrap); */ white-space: nowrap; overflow: hidden; @@ -1616,11 +1034,6 @@ </style> - - - - - </head> <body><div hidden="" by-vulcanize=""><dom-module id="iron-list" assetpath="chrome://resources/polymer/v1_0/iron-list/"> <template> @@ -1661,144 +1074,6 @@ </template> </dom-module> -<dom-module id="paper-header-panel" assetpath="chrome://resources/polymer/v1_0/paper-header-panel/"> - - <style> -/** -@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 -*/ - -:host { - --paper-header-panel-shadow: { - height: 6px; - bottom: -6px; - box-shadow: inset 0px 5px 6px -3px rgba(0, 0, 0, 0.4); - }; - - @apply(--layout-vertical); - - position: relative; - height: 100%; -} - -#mainContainer { - @apply(--layout-flex); - - position: relative; - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; -} - -#mainPanel { - @apply(--layout-vertical); - @apply(--layout-flex); - - position: relative; -} - -/* - * mode: scroll - */ -:host([mode=scroll]) #mainContainer { - @apply(--paper-header-panel-scroll-container); - - overflow: visible; -} - -:host([mode=scroll]) { - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; -} - -/* - * mode: cover - */ -:host([mode=cover]) #mainContainer { - @apply(--paper-header-panel-cover-container); - - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -:host([mode=cover]) #mainPanel { - position: static; -} - -/* - * mode: standard - */ -:host([mode=standard]) #mainContainer { - @apply(--paper-header-panel-standard-container); -} - -/* - * mode: seamed - */ -:host([mode=seamed]) #mainContainer { - @apply(--paper-header-panel-seamed-container); -} - - -/* - * mode: waterfall - */ -:host([mode=waterfall]) #mainContainer { - @apply(--paper-header-panel-waterfall-container); -} - -/* - * mode: waterfall-tall - */ -:host([mode=waterfall-tall]) #mainContainer { - @apply(--paper-header-panel-waterfall-tall-container); -} - -#dropShadow { - @apply(--paper-header-panel-shadow); - - position: absolute; - top: 0; - left: 0; - right: 0; - height: 6px; - pointer-events: none; - - -webkit-transition: opacity 0.5s; - transition: opacity 0.5s; - - opacity: 0; -} - -#dropShadow.has-shadow { - opacity: 1; -} - -</style> - - <template> - <content id="headerContent" select="paper-toolbar, .paper-header"></content> - - <div id="mainPanel"> - <div id="mainContainer" class$="[[_computeMainContainerClass(mode)]]"> - <content id="mainContent" select="*"></content> - </div> - <div id="dropShadow"></div> - </div> - </template> - -</dom-module> - <dom-module id="iron-icon" assetpath="chrome://resources/polymer/v1_0/iron-icon/"> <style> @@ -1809,7 +1084,8 @@ vertical-align: middle; - fill: currentcolor; + fill: var(--iron-icon-fill-color, currentcolor); + stroke: var(--iron-icon-stroke-color, none); width: var(--iron-icon-width, 24px); height: var(--iron-icon-height, 24px); @@ -2123,10 +1399,6 @@ transform: translate3d(0, 0, 0); } - :host([noink]) { - pointer-events: none; - } - #background, #waves, .wave-container, @@ -2169,37 +1441,38 @@ </template> </dom-module> <dom-module id="paper-material" assetpath="chrome://resources/polymer/v1_0/paper-material/"> - <style> - :host { - display: block; - position: relative; - } - - :host([animated]) { - @apply(--shadow-transition); - } - - :host([elevation="1"]) { - @apply(--shadow-elevation-2dp); - } - - :host([elevation="2"]) { - @apply(--shadow-elevation-4dp); - } - - :host([elevation="3"]) { - @apply(--shadow-elevation-6dp); - } - - :host([elevation="4"]) { - @apply(--shadow-elevation-8dp); - } - - :host([elevation="5"]) { - @apply(--shadow-elevation-16dp); - } - </style> <template> + <style> + :host { + display: block; + position: relative; + } + + :host([animated]) { + @apply(--shadow-transition); + } + + :host([elevation="1"]) { + @apply(--shadow-elevation-2dp); + } + + :host([elevation="2"]) { + @apply(--shadow-elevation-4dp); + } + + :host([elevation="3"]) { + @apply(--shadow-elevation-6dp); + } + + :host([elevation="4"]) { + @apply(--shadow-elevation-8dp); + } + + :host([elevation="5"]) { + @apply(--shadow-elevation-16dp); + } + </style> + <content></content> </template> </dom-module> @@ -2546,6 +1819,10 @@ --downloads-item-width: 622px; } +[hidden] { + display: none !important; +} + paper-button { font-weight: 500; margin: 0; @@ -2793,6 +2070,7 @@ content: ''; background: currentColor; opacity: var(--dark-divider-opacity); + pointer-events: none; @apply(--paper-item-focused-before); } @@ -2816,72 +2094,63 @@ </template> </dom-module> -<dom-module id="paper-menu" assetpath="chrome://resources/polymer/v1_0/paper-menu/"> - <style> -/** -@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 -*/ - -/* need a wrapper element to make this higher specificity than the :host rule in paper-item */ -.selectable-content > ::content > .iron-selected { - font-weight: bold; - - @apply(--paper-menu-selected-item); -} - -.selectable-content > ::content > [disabled] { - color: var(--paper-menu-disabled-color, --disabled-text-color); -} - -.selectable-content > ::content > *:focus { - position: relative; - outline: 0; - - @apply(--paper-menu-focused-item); -} - -.selectable-content > ::content > *:focus:after { - @apply(--layout-fit); - background: currentColor; - opacity: var(--dark-divider-opacity); - content: ''; - - @apply(--paper-menu-focused-item-after); -} - -.selectable-content > ::content > *[colored]:focus:after { - opacity: 0.26; -} - -</style> - - <style> - :host { - display: block; - padding: 8px 0; - - background: var(--paper-menu-background-color, --primary-background-color); - color: var(--paper-menu-color, --primary-text-color); - - @apply(--paper-menu); - } - </style> +<dom-module id="paper-menu-shared-styles" assetpath="chrome://resources/polymer/v1_0/paper-menu/"> <template> + <style> + /* need a wrapper element to make this higher specificity than the :host rule in paper-item */ + .selectable-content > ::content > .iron-selected { + font-weight: bold; + + @apply(--paper-menu-selected-item); + } + + .selectable-content > ::content > [disabled] { + color: var(--paper-menu-disabled-color, --disabled-text-color); + } + + .selectable-content > ::content > *:focus { + position: relative; + outline: 0; + + @apply(--paper-menu-focused-item); + } + + .selectable-content > ::content > *:focus:after { + @apply(--layout-fit); + background: currentColor; + opacity: var(--dark-divider-opacity); + content: ''; + + @apply(--paper-menu-focused-item-after); + } + + .selectable-content > ::content > *[colored]:focus:after { + opacity: 0.26; + } + </style> + </template> +</dom-module> +<dom-module id="paper-menu" assetpath="chrome://resources/polymer/v1_0/paper-menu/"> + <template> + <style include="paper-menu-shared-styles"></style> + <style> + :host { + display: block; + padding: 8px 0; + + background: var(--paper-menu-background-color, --primary-background-color); + color: var(--paper-menu-color, --primary-text-color); + + @apply(--paper-menu); + } + </style> <div class="selectable-content"> <content></content> </div> - </template> -</dom-module> - + </dom-module> <dom-module id="iron-overlay-backdrop" assetpath="chrome://resources/polymer/v1_0/iron-overlay-behavior/"> <style> @@ -3061,6 +2330,7 @@ .focused-line { height: 2px; + @apply(--layout-fit); -webkit-transform-origin: center center; transform-origin: center center; @@ -3094,6 +2364,7 @@ .unfocused-line { height: 1px; + @apply(--layout-fit); background: var(--paper-input-container-color, --secondary-text-color); @apply(--paper-input-container-underline); @@ -3127,6 +2398,7 @@ font: inherit; color: var(--paper-input-container-color, --secondary-text-color); + @apply(--paper-font-common-nowrap); @apply(--paper-font-subhead); @apply(--paper-input-container-label); } @@ -3135,14 +2407,29 @@ .input-content.label-is-floating ::content .paper-input-label { -webkit-transform: translateY(-75%) scale(0.75); transform: translateY(-75%) scale(0.75); - -webkit-transform-origin: left top; - transform-origin: left top; -webkit-transition: -webkit-transform 0.25s; transition: transform 0.25s; + -webkit-transform-origin: left top; + transform-origin: left top; + + /* Since we scale to 75/100 of the size, we actually have 100/75 of the + original space now available */ + width: 133%; + @apply(--paper-transition-easing); } + :host-context([dir="rtl"]) .input-content.label-is-floating ::content label, + :host-context([dir="rtl"]) .input-content.label-is-floating ::content .paper-input-label { + /* TODO(noms): Figure out why leaving the width at 133% before the animation + * actually makes + * it wider on the right side, not left side, as you would expect in RTL */ + width: 100%; + -webkit-transform-origin: right top; + transform-origin: right top; + } + .input-content.label-is-highlighted ::content label, .input-content.label-is-highlighted ::content .paper-input-label { color: var(--paper-input-container-focus-color, --default-primary-color); @@ -3173,6 +2460,7 @@ border: none; color: var(--paper-input-container-input-color, --primary-text-color); -webkit-appearance: none; + text-align: inherit; @apply(--paper-font-subhead); @apply(--paper-input-container-input); @@ -3197,6 +2485,10 @@ resize: none; } + .add-on-content { + position: relative; + } + .add-on-content.is-invalid ::content * { color: var(--paper-input-container-invalid-color, --google-red-500); } @@ -3212,15 +2504,16 @@ <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focused,invalid,_inputHasContent)]]"> <content select="[prefix]" id="prefix"></content> - <div class="label-and-input-container"> + + <div class="label-and-input-container" id="labelAndInputContainer"> <content select=":not([add-on]):not([prefix]):not([suffix])"></content> </div> <content select="[suffix]"></content> </div> <div class$="[[_computeUnderlineClass(focused,invalid)]]"> - <div class="unfocused-line fit"></div> - <div class="focused-line fit"></div> + <div class="unfocused-line"></div> + <div class="focused-line"></div> </div> <div class$="[[_computeAddOnContentClass(focused,invalid)]]"> @@ -3344,6 +2637,10 @@ --downloads-item-width: 622px; } +[hidden] { + display: none !important; +} + paper-button { font-weight: 500; margin: 0; @@ -3380,7 +2677,7 @@ width: var(--downloads-item-width); } -:host-context(.loading) #actions { +:host-context([loading]) #actions { visibility: hidden; } @@ -3469,21 +2766,19 @@ </dom-module> <dom-module id="downloads-manager" assetpath="chrome://downloads/"> <template> - <paper-header-panel id="panel" class="loading"> - <downloads-toolbar class="paper-header" id="toolbar"></downloads-toolbar> - <iron-list id="downloads-list" items="{{items_}}" hidden="[[!hasDownloads_]]"> - <template> - <downloads-item data="[[item]]" hide-date="[[item.hideDate]]"> - </downloads-item> - </template> - </iron-list> - <div id="no-downloads" hidden="[[hasDownloads_]]"> - <div> - <div class="illustration"></div> - <span></span> - </div> + <downloads-toolbar id="toolbar"></downloads-toolbar> + <iron-list id="downloads-list" items="{{items_}}" hidden="[[!hasDownloads_]]"> + <template> + <downloads-item data="[[item]]" hide-date="[[item.hideDate]]"> + </downloads-item> + </template> + </iron-list> + <div id="no-downloads" hidden="[[hasDownloads_]]"> + <div> + <div class="illustration"></div> + <span></span> </div> - </paper-header-panel> + </div> </template> <style> /* Copyright 2015 The Chromium Authors. All rights reserved. @@ -3494,6 +2789,10 @@ --downloads-item-width: 622px; } +[hidden] { + display: none !important; +} + paper-button { font-weight: 500; margin: 0; @@ -3511,6 +2810,7 @@ flex: 1 0; flex-direction: column; height: 100%; + overflow-y: overlay; } @media screen and (max-width: 1024px) { @@ -3519,23 +2819,13 @@ } } -#panel { - --paper-header-panel-shadow: { - display: none; - }; - --paper-header-panel-standard-container: { - display: flex; - overflow-y: overlay; - }; -} - #no-downloads, #downloads-list { flex: 1; } -.loading #no-downloads, -.loading #downloads-list { +:host([loading]) #no-downloads, +:host([loading]) #downloads-list { display: none; } @@ -3568,4 +2858,4 @@ <command id="undo-command" shortcut="Ctrl-U+005A"></command> </if> - </body></html> \ No newline at end of file + <script src="crisper.js"></script></body></html> \ No newline at end of file
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html index 0015d83..5349957 100644 --- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html +++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
@@ -90,9 +90,7 @@ </div> <div class="sink-text route" hidden$="[[computeRouteInSinkListHidden_(item.id, sinkToRouteMap_)]]"> - <span>[[ - computeRouteInSinkListValue_(item.id, sinkToRouteMap_) - ]]</span> + <span>[[computeRouteInSinkListValue_(item.id, sinkToRouteMap_)]]</span> </div> </div> </div>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js index 938b356..6c8edeb 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js
@@ -185,11 +185,20 @@ * @private */ setFontsData_: function(fontList, encodingList) { - this.$.standardFont.menuOptions = fontList; - this.$.serifFont.menuOptions = fontList; - this.$.sansSerifFont.menuOptions = fontList; - this.$.fixedFont.menuOptions = fontList; - this.$.encoding.menuOptions = encodingList; + var fontMenuOptions = []; + for (var i = 0; i < fontList.length; ++i) + fontMenuOptions.push({value: fontList[i][0], name: fontList[i][1]}); + this.$.standardFont.menuOptions = fontMenuOptions; + this.$.serifFont.menuOptions = fontMenuOptions; + this.$.sansSerifFont.menuOptions = fontMenuOptions; + this.$.fixedFont.menuOptions = fontMenuOptions; + + var encodingMenuOptions = []; + for (var i = 0; i < encodingList.length; ++i) { + encodingMenuOptions.push({ + value: encodingList[i][0], name: encodingList[i][1]}); + } + this.$.encoding.menuOptions = encodingMenuOptions; }, /**
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index 63957d4..797cb96 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -5,6 +5,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> +<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html"> <link rel="import" href="chrome://md-settings/controls/settings_input.html"> <link rel="import" href="chrome://md-settings/controls/settings_radio_group.html"> <link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html"> @@ -85,7 +86,7 @@ <div class="settings-box split"> <div class="start" i18n-content="pageZoom"></div> <settings-dropdown-menu id="pageZoom" - pref="{{prefs.partition.default_zoom_level}}" + pref="{{defaultZoomLevel_}}" menu-options="[[pageZoomOptions_]]"> </settings-dropdown-menu> </div>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chrome/browser/resources/settings/appearance_page/appearance_page.js index c38b25e..52691cb9 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -30,6 +30,14 @@ }, /** + * Preferences state. + */ + prefs: { + type: Object, + notify: true, + }, + + /** * @private */ allowResetTheme_: { @@ -39,32 +47,78 @@ }, /** + * @private + */ + defaultZoomLevel_: { + notify: true, + type: Object, + value: function() { + return { + type: chrome.settingsPrivate.PrefType.NUMBER, + }; + }, + }, + + /** * List of options for the font size drop-down menu. - * The order of entries in this array matches the - * prefs.browser.clear_data.time_period.value enum. - * @private {!Array<!Array<{0: number, 1: string}>>} + * @type {!DropdownMenuOptionList} */ fontSizeOptions_: { readOnly: true, type: Array, value: function() { return [ - [9, loadTimeData.getString('verySmall')], - [12, loadTimeData.getString('small')], - [16, loadTimeData.getString('medium')], - [20, loadTimeData.getString('large')], - [24, loadTimeData.getString('veryLarge')], + {value: 9, name: loadTimeData.getString('verySmall')}, + {value: 12, name: loadTimeData.getString('small')}, + {value: 16, name: loadTimeData.getString('medium')}, + {value: 20, name: loadTimeData.getString('large')}, + {value: 24, name: loadTimeData.getString('veryLarge')}, ]; }, }, + + /** + * List of options for the page zoom drop-down menu. + * @type {!DropdownMenuOptionList} + */ + pageZoomOptions_: { + readOnly: true, + type: Array, + value: [ + {value: 25, name: '25%'}, + {value: 33, name: '33%'}, + {value: 50, name: '50%'}, + {value: 67, name: '67%'}, + {value: 75, name: '75%'}, + {value: 90, name: '90%'}, + {value: 100, name: '100%'}, + {value: 110, name: '110%'}, + {value: 125, name: '125%'}, + {value: 150, name: '150%'}, + {value: 175, name: '175%'}, + {value: 200, name: '200%'}, + {value: 300, name: '300%'}, + {value: 400, name: '400%'}, + {value: 500, name: '500%'}, + ], + }, }, behaviors: [ I18nBehavior, ], + observers: [ + 'zoomLevelChanged_(defaultZoomLevel_.value)', + ], + ready: function() { this.$.defaultFontSize.menuOptions = this.fontSizeOptions_; + this.$.pageZoom.menuOptions = this.pageZoomOptions_; + // TODO(dschuyler): Look into adding a listener for the + // default zoom percent. + chrome.settingsPrivate.getDefaultZoomPercent( + this.zoomPrefChanged_.bind(this)); }, /** @override */ @@ -104,4 +158,23 @@ showFontsPage_: function() { return this.currentRoute.subpage[0] == 'appearance-fonts'; }, + + /** + * @param {number} percent The integer percentage of the page zoom. + * @private + */ + zoomPrefChanged_: function(percent) { + this.set('defaultZoomLevel_.value', percent); + }, + + /** + * @param {number} percent The integer percentage of the page zoom. + * @private + */ + zoomLevelChanged_: function(percent) { + // The |percent| may be undefined on startup. + if (percent === undefined) + return; + chrome.settingsPrivate.setDefaultZoomPercent(percent); + }, });
diff --git a/chrome/browser/resources/settings/appearance_page/compiled_resources.gyp b/chrome/browser/resources/settings/appearance_page/compiled_resources.gyp index 7e7c57b7..9f5b2b1 100644 --- a/chrome/browser/resources/settings/appearance_page/compiled_resources.gyp +++ b/chrome/browser/resources/settings/appearance_page/compiled_resources.gyp
@@ -20,6 +20,8 @@ '../../../../../third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js', '../../../../../third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js', '../../../../../third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js', + '../controls/settings_dropdown_menu.js', + '../prefs/pref_util.js' ], 'externs': [ '../../../../../third_party/closure_compiler/externs/settings_private.js' @@ -35,6 +37,8 @@ '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data', '../../../../../ui/webui/resources/js/cr.js', '../../../../../ui/webui/resources/js/i18n_behavior.js', + '../controls/settings_dropdown_menu.js', + '../prefs/pref_util.js', '../settings_page/settings_animated_pages.js' ], 'externs': [
diff --git a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html index 3371261..3ecec290 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html +++ b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.html
@@ -15,7 +15,7 @@ <span i18n-content="clearFollowingItemsFrom"></span> <settings-dropdown-menu id="clearFrom" pref="{{prefs.browser.clear_data.time_period}}" - menu-options="[[clearFromOptions_]]" disabled> + menu-options="[[clearFromOptions_]]"> </settings-dropdown-menu> <settings-checkbox id="browsingCheckbox" pref="{{prefs.browser.clear_data.browsing_history}}"
diff --git a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js index b60dd612..5a9b14c 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js +++ b/chrome/browser/resources/settings/clear_browsing_data_page/clear_browsing_data_page.js
@@ -40,19 +40,17 @@ /** * List of options for the dropdown menu. - * The order of entries in this array matches the - * prefs.browser.clear_data.time_period.value enum. - * @private {!Array<!Array<number, string>>} + * @private {!DropdownMenuOptionList>} */ clearFromOptions_: { readOnly: true, type: Array, value: [ - [0, loadTimeData.getString('clearDataHour')], - [1, loadTimeData.getString('clearDataDay')], - [2, loadTimeData.getString('clearDataWeek')], - [3, loadTimeData.getString('clearData4Weeks')], - [4, loadTimeData.getString('clearDataEverything')], + {value: 0, name: loadTimeData.getString('clearDataHour')}, + {value: 1, name: loadTimeData.getString('clearDataDay')}, + {value: 2, name: loadTimeData.getString('clearDataWeek')}, + {value: 3, name: loadTimeData.getString('clearData4Weeks')}, + {value: 4, name: loadTimeData.getString('clearDataEverything')}, ], }, },
diff --git a/chrome/browser/resources/settings/controls/compiled_resources.gyp b/chrome/browser/resources/settings/controls/compiled_resources.gyp index 043d0c72..7a9a788 100644 --- a/chrome/browser/resources/settings/controls/compiled_resources.gyp +++ b/chrome/browser/resources/settings/controls/compiled_resources.gyp
@@ -7,10 +7,10 @@ 'target_name': 'settings_checkbox', 'variables': { 'depends': [ - '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert', - '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data', '../../../../../ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js', '../../../../../ui/webui/resources/cr_elements/policy/cr_policy_pref_behavior.js', + '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert', + '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data', ], 'externs': [ '../../../../../third_party/closure_compiler/externs/settings_private.js' @@ -38,10 +38,10 @@ 'target_name': 'settings_input', 'variables': { 'depends': [ - '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert', - '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data', '../../../../../ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js', '../../../../../ui/webui/resources/cr_elements/policy/cr_policy_pref_behavior.js', + '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert', + '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data', ], 'externs': [ '../../../../../third_party/closure_compiler/externs/settings_private.js'
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.html b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html index 2c796421..4e771932 100644 --- a/chrome/browser/resources/settings/controls/settings_dropdown_menu.html +++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
@@ -15,7 +15,7 @@ <paper-menu class="dropdown-content" selected="{{selected_}}" attr-for-selected="data-value"> <template is="dom-repeat" items="[[menuOptions]]"> - <paper-item data-value$="[[item.0]]">[[item.1]]</paper-item> + <paper-item data-value$="[[item.value]]">[[item.name]]</paper-item> </template> <paper-item data-value$="[[notFoundValue_]]" hidden$="[[!isSelectedNotFound_(selected_)]]">
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.js b/chrome/browser/resources/settings/controls/settings_dropdown_menu.js index 95f86ac..9bfa1d7 100644 --- a/chrome/browser/resources/settings/controls/settings_dropdown_menu.js +++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
@@ -2,14 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - /** - * This tuple is made up of a (value, name, attribute). The value and name are - * used by the dropdown menu. The attribute is optional 'user data' that is - * ignored by the dropdown menu. +/** + * The |name| is shown in the gui. The |value| us use to set or compare with + * the preference value. * @typedef {{ - * 0: (number|string), - * 1: string, - * 2: (string|undefined) + * name: string, + * value: (number|string) * }} */ var DropdownMenuOption; @@ -40,7 +38,6 @@ /** * List of options for the drop-down menu. - * TODO(michaelpg): use named properties instead of indices. * @type {DropdownMenuOptionList} */ menuOptions: { @@ -139,7 +136,7 @@ return; var prefValue = this.pref.value; var option = this.menuOptions.find(function(menuItem) { - return menuItem[0] == prefValue; + return menuItem.value == prefValue; }); if (option == undefined) this.selected_ = this.notFoundValue_;
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.css b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.css deleted file mode 100644 index 8fcdf8f..0000000 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.css +++ /dev/null
@@ -1,8 +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. */ - -.option-value { - color: gray; - font-size: 80%; -}
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html index aa649e80..6041ca6 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html
@@ -1,20 +1,38 @@ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item-body.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <dom-module id="settings-passwords-and-forms-page"> <link rel="import" type="css" href="chrome://md-settings/settings_page/settings_page.css"> - <link rel="import" type="css" - href="chrome://md-settings/passwords_and_forms_page/passwords_and_forms_page.css"> <template> <div class="settings-box"> - <paper-item-body two-line class="flex"> - <div i18n-content="autofill"></div> - <div class="option-value" i18n-content="autofillDetail"></div> + <paper-item> + <paper-item-body two-line> + <div i18n-content="autofill"></div> + <div secondary i18n-content="autofillDetail"></div> + </paper-item-body> + <paper-toggle-button + checked="{{prefs.autofill.enabled.value}}"> + </paper-toggle-button> + <cr-expand-button disabled="{{!prefs.autofill.enabled.value}}"> + </cr-expand-button> </paper-item> - <paper-item-body two-line class="flex"> - <div i18n-content="passwords"></div> - <div class="option-value" i18n-content="passwordsDetail"></div> + </div> + <div class="settings-box"> + <paper-item> + <paper-item-body two-line> + <div i18n-content="passwords"></div> + <div secondary i18n-content="passwordsDetail"></div> + </paper-item-body> + <paper-toggle-button + checked="{{prefs.profile.password_manager_enabled.value}}"> + </paper-toggle-button> + <cr-expand-button + disabled="{{!prefs.profile.password_manager_enabled.value}}"> + </cr-expand-button> </paper-item> </div> </template>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js index 7dcb050..cb48dbe1 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js
@@ -14,5 +14,15 @@ Polymer({ is: 'settings-passwords-and-forms-page', + + properties: { + /** + * Preferences state. + */ + prefs: { + type: Object, + notify: true, + }, + }, }); })();
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.css b/chrome/browser/resources/settings/privacy_page/privacy_page.css index bcd874e..cebdb9a 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.css +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.css
@@ -2,6 +2,10 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +paper-item { + --paper-item-min-height: 24px; +} + .privacy-buttons { margin-top: 25px; -} \ No newline at end of file +}
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index a679f1a..410da507 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -3,6 +3,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item-body.html"> <link rel="import" href="chrome://md-settings/certificate_manager_page/certificate_manager_page.html"> <link rel="import" href="chrome://md-settings/clear_browsing_data_page/clear_browsing_data_page.html"> <link rel="import" href="chrome://md-settings/controls/settings_checkbox.html"> @@ -68,18 +69,23 @@ </settings-checkbox> </if> </div> - <div class="settings-box end-justified"> - <paper-button - on-tap="onManageCertificatesTap_" - i18n-content="manageCertificates"> - </paper-button> - <paper-button - on-tap="onSiteSettingsTap_" - i18n-content="siteSettings"> - </paper-button> - <paper-button - on-tap="onClearBrowsingDataTap_" - raised i18n-content="clearBrowsingData"> + <div class="settings-box" on-tap="onManageCertificatesTap_"> + <paper-item> + <paper-item-body> + <div i18n-content="manageCertificates"></div> + </paper-item-body> + </paper-item> + </div> + <div class="settings-box" on-tap="onSiteSettingsTap_"> + <paper-item> + <paper-item-body> + <div i18n-content="siteSettings"></div> + </paper-item-body> + </paper-item> + </div> + <div class="settings-box"> + <paper-button on-tap="onClearBrowsingDataTap_" + i18n-content="clearBrowsingData"> </paper-button> </div> </neon-animatable>
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html index 907ae18..2282aff 100644 --- a/chrome/browser/resources/settings/settings_menu/settings_menu.html +++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -1,5 +1,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/device-icons.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/hardware-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/social-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-icon-item.html"> @@ -50,6 +52,12 @@ <span i18n-content="usersPageTitle"></span> </paper-icon-item> </if> +<if expr="not chromeos"> + <paper-icon-item> + <iron-icon icon="open-in-browser" item-icon></iron-icon> + <span i18n-content="defaultBrowser"></span> + </paper-icon-item> +</if> </paper-menu> </paper-submenu> <paper-submenu data-page="advanced" on-tap="openPage_"> @@ -58,6 +66,10 @@ <span i18n-content="advancedPageTitle"></span> </paper-icon-item> <paper-menu class="menu-content"> + <paper-icon-item> + <iron-icon icon="communication:location-on" item-icon></iron-icon> + <span i18n-content="siteSettingsLocation"></span> + </paper-icon-item> <if expr="chromeos"> <paper-icon-item> <iron-icon icon="device:access-time" item-icon></iron-icon> @@ -65,7 +77,7 @@ </paper-icon-item> </if> <paper-icon-item> - <iron-icon icon="lock" item-icon></iron-icon> + <iron-icon icon="hardware:security" item-icon></iron-icon> <span i18n-content="privacyPageTitle"></span> </paper-icon-item> <if expr="chromeos"> @@ -75,9 +87,21 @@ </paper-icon-item> </if> <paper-icon-item> + <iron-icon icon="lock" item-icon></iron-icon> + <span i18n-content="passwordsAndAutofillPageTitle"></span> + </paper-icon-item> + <paper-icon-item> + <iron-icon icon="language" item-icon></iron-icon> + <span i18n-content="languagesPageTitle"></span> + </paper-icon-item> + <paper-icon-item> <iron-icon icon="file-download" item-icon></iron-icon> <span i18n-content="downloadsPageTitle"></span> </paper-icon-item> + <paper-icon-item> + <iron-icon icon="settings-backup-restore" item-icon></iron-icon> + <span i18n-content="resetPageTitle"></span> + </paper-icon-item> <if expr="chromeos"> <paper-icon-item> <iron-icon icon="accessibility" item-icon></iron-icon>
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 7577f20..7723bac2 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -298,9 +298,6 @@ file="languages_page/edit_dictionary_page.js" type="chrome_html" /> </if> - <structure name="IDR_SETTINGS_PASSWORDS_AND_FORMS_PAGE_CSS" - file="passwords_and_forms_page/passwords_and_forms_page.css" - type="chrome_html" /> <structure name="IDR_SETTINGS_PASSWORDS_AND_FORMS_PAGE_HTML" file="passwords_and_forms_page/passwords_and_forms_page.html" type="chrome_html" />
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc index 02533fa..2667097 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -33,6 +33,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" #include "components/google/core/browser/google_util.h" +#include "components/security_interstitials/core/controller_client.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/interstitial_page.h" #include "content/public/browser/navigation_controller.h" @@ -238,17 +239,17 @@ DCHECK(retval) << page_cmd; switch (command) { - case CMD_DO_REPORT: { + case security_interstitials::CMD_DO_REPORT: { // User enabled SB Extended Reporting via the checkbox. SetReportingPreference(true); break; } - case CMD_DONT_REPORT: { + case security_interstitials::CMD_DONT_REPORT: { // User disabled SB Extended Reporting via the checkbox. SetReportingPreference(false); break; } - case CMD_OPEN_HELP_CENTER: { + case security_interstitials::CMD_OPEN_HELP_CENTER: { // User pressed "Learn more". metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::SHOW_LEARN_MORE); @@ -265,12 +266,12 @@ web_contents()->OpenURL(params); break; } - case CMD_OPEN_REPORTING_PRIVACY: { + case security_interstitials::CMD_OPEN_REPORTING_PRIVACY: { // User pressed on the SB Extended Reporting "privacy policy" link. OpenExtendedReportingPrivacyPolicy(); break; } - case CMD_PROCEED: { + case security_interstitials::CMD_PROCEED: { // User pressed on the button to proceed. if (!IsPrefEnabled(prefs::kSafeBrowsingProceedAnywayDisabled)) { metrics_helper()->RecordUserDecision( @@ -281,7 +282,7 @@ } // If the user can't proceed, fall through to CMD_DONT_PROCEED. } - case CMD_DONT_PROCEED: { + case security_interstitials::CMD_DONT_PROCEED: { // User pressed on the button to return to safety. // Don't record the user action here because there are other ways of // triggering DontProceed, like clicking the back button. @@ -306,7 +307,7 @@ } break; } - case CMD_OPEN_DIAGNOSTIC: { + case security_interstitials::CMD_OPEN_DIAGNOSTIC: { // User wants to see why this page is blocked. const UnsafeResource& unsafe_resource = unsafe_resources_[0]; std::string bad_url_spec = unsafe_resource.url.spec(); @@ -328,13 +329,13 @@ web_contents()->OpenURL(params); break; } - case CMD_SHOW_MORE_SECTION: { + case security_interstitials::CMD_SHOW_MORE_SECTION: { // User has opened up the hidden text. metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::SHOW_ADVANCED); break; } - case CMD_REPORT_PHISHING_ERROR: { + case security_interstitials::CMD_REPORT_PHISHING_ERROR: { // User wants to report a phishing error. metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::REPORT_PHISHING_ERROR); @@ -632,19 +633,20 @@ base::DictionaryValue* load_time_data) { // Only show checkbox if !(HTTPS || incognito-mode). const bool show = CanShowThreatDetailsOption(); - load_time_data->SetBoolean(interstitials::kDisplayCheckBox, show); + load_time_data->SetBoolean(security_interstitials::kDisplayCheckBox, show); if (!show) return; const std::string privacy_link = base::StringPrintf( - interstitials::kPrivacyLinkHtml, CMD_OPEN_REPORTING_PRIVACY, + security_interstitials::kPrivacyLinkHtml, + security_interstitials::CMD_OPEN_REPORTING_PRIVACY, l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str()); load_time_data->SetString( - interstitials::kOptInLink, + security_interstitials::kOptInLink, l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE, base::UTF8ToUTF16(privacy_link))); load_time_data->SetBoolean( - interstitials::kBoxChecked, + security_interstitials::kBoxChecked, IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled)); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc index 98668c9..e88dfe1b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -33,6 +33,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/test_switches.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/security_interstitials/core/controller_client.h" #include "components/security_interstitials/core/metrics_helper.h" #include "content/public/browser/interstitial_page.h" #include "content/public/browser/navigation_controller.h" @@ -429,7 +430,7 @@ } void SendCommand( - SecurityInterstitialPage::SecurityInterstitialCommands command) { + security_interstitials::SecurityInterstitialCommands command) { WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); // We use InterstitialPage::GetInterstitialPage(tab) instead of @@ -529,7 +530,7 @@ // below, and crbug.com/76460), we use SendCommand to trigger the callback // directly rather than using ClickAndWaitForDetach since there might not // be a notification to wait for. - SendCommand(SecurityInterstitialPage::CMD_PROCEED); + SendCommand(security_interstitials::CMD_PROCEED); } content::RenderViewHost* GetRenderViewHost() { @@ -783,7 +784,7 @@ EXPECT_TRUE(Click("details-button")); EXPECT_EQ(HIDDEN, GetVisibility("proceed-link")); EXPECT_EQ(HIDDEN, GetVisibility("final-paragraph")); - SendCommand(SecurityInterstitialPage::CMD_PROCEED); + SendCommand(security_interstitials::CMD_PROCEED); // The "proceed" command should go back instead, if proceeding is disabled. AssertNoInterstitial(true);
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc index 3026278..36b3dc3 100644 --- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc +++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
@@ -42,7 +42,7 @@ // This class sends a request to GAIA to revoke the given refresh token from // the server. This is a best effort attempt only. This class deletes itself -// when done sucessfully or otherwise. +// when done successfully or otherwise. class MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken : public GaiaAuthConsumer { public:
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.cc b/chrome/browser/ssl/bad_clock_blocking_page.cc index 6ad49b92..a3b3a7b 100644 --- a/chrome/browser/ssl/bad_clock_blocking_page.cc +++ b/chrome/browser/ssl/bad_clock_blocking_page.cc
@@ -29,6 +29,7 @@ #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/google/core/browser/google_util.h" +#include "components/security_interstitials/core/controller_client.h" #include "components/ssl_errors/error_classification.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/cert_store.h" @@ -326,32 +327,32 @@ bool retval = base::StringToInt(command, &cmd); DCHECK(retval); switch (cmd) { - case CMD_DONT_PROCEED: + case security_interstitials::CMD_DONT_PROCEED: interstitial_page()->DontProceed(); break; - case CMD_DO_REPORT: + case security_interstitials::CMD_DO_REPORT: SetReportingPreference(true); break; - case CMD_DONT_REPORT: + case security_interstitials::CMD_DONT_REPORT: SetReportingPreference(false); break; - case CMD_SHOW_MORE_SECTION: + case security_interstitials::CMD_SHOW_MORE_SECTION: metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::SHOW_ADVANCED); break; - case CMD_OPEN_DATE_SETTINGS: + case security_interstitials::CMD_OPEN_DATE_SETTINGS: metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::OPEN_TIME_SETTINGS); content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, base::Bind(&LaunchDateAndTimeSettings)); break; - case CMD_OPEN_REPORTING_PRIVACY: + case security_interstitials::CMD_OPEN_REPORTING_PRIVACY: OpenExtendedReportingPrivacyPolicy(); break; - case CMD_PROCEED: - case CMD_OPEN_HELP_CENTER: - case CMD_RELOAD: - case CMD_OPEN_DIAGNOSTIC: + case security_interstitials::CMD_PROCEED: + case security_interstitials::CMD_OPEN_HELP_CENTER: + case security_interstitials::CMD_RELOAD: + case security_interstitials::CMD_OPEN_DIAGNOSTIC: // Not supported for the bad clock interstitial. NOTREACHED() << "Unexpected command: " << command; }
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.cc b/chrome/browser/ssl/captive_portal_blocking_page.cc index 652f66a..adeca5bd 100644 --- a/chrome/browser/ssl/captive_portal_blocking_page.cc +++ b/chrome/browser/ssl/captive_portal_blocking_page.cc
@@ -18,6 +18,7 @@ #include "chrome/common/pref_names.h" #include "components/captive_portal/captive_portal_detector.h" #include "components/certificate_reporting/error_reporter.h" +#include "components/security_interstitials/core/controller_client.h" #include "components/url_formatter/url_formatter.h" #include "components/wifi/wifi_service.h" #include "content/public/browser/web_contents.h" @@ -183,7 +184,7 @@ if (cert_report_helper_) cert_report_helper_->PopulateExtendedReportingOption(load_time_data); else - load_time_data->SetBoolean(interstitials::kDisplayCheckBox, false); + load_time_data->SetBoolean(security_interstitials::kDisplayCheckBox, false); } void CaptivePortalBlockingPage::CommandReceived(const std::string& command) { @@ -196,7 +197,7 @@ bool command_is_num = base::StringToInt(command, &command_num); DCHECK(command_is_num) << command; // Any command other than "open the login page" is ignored. - if (command_num == CMD_OPEN_LOGIN) { + if (command_num == security_interstitials::CMD_OPEN_LOGIN) { RecordUMA(OPEN_LOGIN_PAGE); CaptivePortalTabHelper::OpenLoginTabForWebContents(web_contents(), true); }
diff --git a/chrome/browser/ssl/cert_report_helper.cc b/chrome/browser/ssl/cert_report_helper.cc index 2e3e120..0d277b2 100644 --- a/chrome/browser/ssl/cert_report_helper.cc +++ b/chrome/browser/ssl/cert_report_helper.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/ssl/ssl_cert_reporter.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" +#include "components/security_interstitials/core/controller_client.h" #include "components/security_interstitials/core/metrics_helper.h" #include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_context.h" @@ -55,21 +56,21 @@ // by policy. const bool show = ShouldShowCertificateReporterCheckbox(); - load_time_data->SetBoolean(interstitials::kDisplayCheckBox, show); + load_time_data->SetBoolean(security_interstitials::kDisplayCheckBox, show); if (!show) return; load_time_data->SetBoolean( - interstitials::kBoxChecked, + security_interstitials::kBoxChecked, IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled)); const std::string privacy_link = base::StringPrintf( - interstitials::kPrivacyLinkHtml, - SecurityInterstitialPage::CMD_OPEN_REPORTING_PRIVACY, + security_interstitials::kPrivacyLinkHtml, + security_interstitials::CMD_OPEN_REPORTING_PRIVACY, l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str()); load_time_data->SetString( - interstitials::kOptInLink, + security_interstitials::kOptInLink, l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE, base::UTF8ToUTF16(privacy_link))); }
diff --git a/chrome/browser/ssl/chrome_security_state_model_client.cc b/chrome/browser/ssl/chrome_security_state_model_client.cc new file mode 100644 index 0000000..b95f8865 --- /dev/null +++ b/chrome/browser/ssl/chrome_security_state_model_client.cc
@@ -0,0 +1,44 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ssl/chrome_security_state_model_client.h" + +#include "base/command_line.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/histogram_macros.h" +#include "chrome/browser/chromeos/policy/policy_cert_service.h" +#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/cert_store.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/ssl_status.h" +#include "net/cert/x509_certificate.h" + +ChromeSecurityStateModelClient::ChromeSecurityStateModelClient( + content::WebContents* web_contents) + : web_contents_(web_contents) {} + +ChromeSecurityStateModelClient::~ChromeSecurityStateModelClient() {} + +bool ChromeSecurityStateModelClient::RetrieveCert( + scoped_refptr<net::X509Certificate>* cert) { + content::NavigationEntry* entry = + web_contents_->GetController().GetVisibleEntry(); + if (!entry) + return false; + return content::CertStore::GetInstance()->RetrieveCert( + entry->GetSSL().cert_id, cert); +} + +bool ChromeSecurityStateModelClient::UsedPolicyInstalledCertificate() { +#if defined(OS_CHROMEOS) + policy::PolicyCertService* service = + policy::PolicyCertServiceFactory::GetForProfile( + Profile::FromBrowserContext(web_contents_->GetBrowserContext())); + if (service && service->UsedPolicyCertificates()) + return true; +#endif + return false; +}
diff --git a/chrome/browser/ssl/chrome_security_state_model_client.h b/chrome/browser/ssl/chrome_security_state_model_client.h new file mode 100644 index 0000000..4889b9c3 --- /dev/null +++ b/chrome/browser/ssl/chrome_security_state_model_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 CHROME_BROWSER_SSL_CHROME_SECURITY_STATE_MODEL_CLIENT_H_ +#define CHROME_BROWSER_SSL_CHROME_SECURITY_STATE_MODEL_CLIENT_H_ + +#include "base/macros.h" +#include "chrome/browser/ssl/security_state_model_client.h" + +namespace content { +class WebContents; +} // namespace content + +// Uses a WebContents to provide a SecurityStateModel with the +// information that it needs to determine the page's security status. +class ChromeSecurityStateModelClient : public SecurityStateModelClient { + public: + explicit ChromeSecurityStateModelClient(content::WebContents* web_contents); + ~ChromeSecurityStateModelClient() override; + + // SecurityStateModelClient: + bool RetrieveCert(scoped_refptr<net::X509Certificate>* cert) override; + bool UsedPolicyInstalledCertificate() override; + + private: + content::WebContents* web_contents_; + + DISALLOW_COPY_AND_ASSIGN(ChromeSecurityStateModelClient); +}; + +#endif // CHROME_BROWSER_SSL_CHROME_SECURITY_STATE_MODEL_CLIENT_H_
diff --git a/chrome/browser/ssl/security_state_model.cc b/chrome/browser/ssl/security_state_model.cc index ace1743..574969e 100644 --- a/chrome/browser/ssl/security_state_model.cc +++ b/chrome/browser/ssl/security_state_model.cc
@@ -9,6 +9,7 @@ #include "base/metrics/histogram_macros.h" #include "base/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ssl/chrome_security_state_model_client.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" @@ -64,14 +65,6 @@ return level; } -scoped_refptr<net::X509Certificate> GetCertForSSLStatus( - const content::SSLStatus& ssl) { - scoped_refptr<net::X509Certificate> cert; - return content::CertStore::GetInstance()->RetrieveCert(ssl.cert_id, &cert) - ? cert - : nullptr; -} - SecurityStateModel::SHA1DeprecationStatus GetSHA1DeprecationStatus( scoped_refptr<net::X509Certificate> cert, const content::SSLStatus& ssl) { @@ -115,7 +108,8 @@ Profile* profile, scoped_refptr<net::X509Certificate> cert, SecurityStateModel::SHA1DeprecationStatus sha1_status, - SecurityStateModel::MixedContentStatus mixed_content_status) { + SecurityStateModel::MixedContentStatus mixed_content_status, + bool used_policy_installed_certificate) { switch (ssl.security_style) { case content::SECURITY_STYLE_UNKNOWN: return SecurityStateModel::NONE; @@ -134,17 +128,13 @@ return SecurityStateModel::SECURITY_WARNING; case content::SECURITY_STYLE_AUTHENTICATED: { -#if defined(OS_CHROMEOS) // Report if there is a policy cert first, before reporting any other // authenticated-but-with-errors cases. A policy cert is a strong // indicator of a MITM being present (the enterprise), while the // other authenticated-but-with-errors indicate something may // be wrong, or may be wrong in the future, but is unclear now. - policy::PolicyCertService* service = - policy::PolicyCertServiceFactory::GetForProfile(profile); - if (service && service->UsedPolicyCertificates()) + if (used_policy_installed_certificate) return SecurityStateModel::SECURITY_POLICY_WARNING; -#endif if (sha1_status == SecurityStateModel::DEPRECATED_SHA1_MAJOR) return SecurityStateModel::SECURITY_ERROR; @@ -217,13 +207,15 @@ return security_info_; } + scoped_refptr<net::X509Certificate> cert = nullptr; + client_->RetrieveCert(&cert); + if (entry->GetURL() == visible_url_ && entry->GetSSL().Equals(visible_ssl_status_)) { // A cert must be present in the CertStore in order for the site to // be considered EV_SECURE, and the cert might have been removed // since the security level was last computed. - if (security_info_.security_level == EV_SECURE && - !GetCertForSSLStatus(visible_ssl_status_)) { + if (security_info_.security_level == EV_SECURE && !cert) { security_info_.security_level = SECURE; } return security_info_; @@ -231,19 +223,21 @@ SecurityInfoForRequest( entry->GetURL(), entry->GetSSL(), - Profile::FromBrowserContext(web_contents_->GetBrowserContext()), - &security_info_); + Profile::FromBrowserContext(web_contents_->GetBrowserContext()), cert, + client_->UsedPolicyInstalledCertificate(), &security_info_); visible_url_ = entry->GetURL(); visible_ssl_status_ = entry->GetSSL(); return security_info_; } // static -void SecurityStateModel::SecurityInfoForRequest(const GURL& url, - const content::SSLStatus& ssl, - Profile* profile, - SecurityInfo* security_info) { - scoped_refptr<net::X509Certificate> cert = GetCertForSSLStatus(ssl); +void SecurityStateModel::SecurityInfoForRequest( + const GURL& url, + const content::SSLStatus& ssl, + Profile* profile, + const scoped_refptr<net::X509Certificate>& cert, + bool used_policy_installed_certificate, + SecurityInfo* security_info) { security_info->cert_id = ssl.cert_id; security_info->sha1_deprecation_status = GetSHA1DeprecationStatus(cert, ssl); security_info->mixed_content_status = GetMixedContentStatus(ssl); @@ -264,8 +258,9 @@ security_info->security_level = GetSecurityLevelForRequest( url, ssl, profile, cert, security_info->sha1_deprecation_status, - security_info->mixed_content_status); + security_info->mixed_content_status, used_policy_installed_certificate); } SecurityStateModel::SecurityStateModel(content::WebContents* web_contents) - : web_contents_(web_contents) {} + : web_contents_(web_contents), + client_(new ChromeSecurityStateModelClient(web_contents)) {}
diff --git a/chrome/browser/ssl/security_state_model.h b/chrome/browser/ssl/security_state_model.h index 8989efb..022435c 100644 --- a/chrome/browser/ssl/security_state_model.h +++ b/chrome/browser/ssl/security_state_model.h
@@ -19,6 +19,7 @@ } // namespace content class Profile; +class SecurityStateModelClient; // SecurityStateModel provides high-level security information about a // page or request. It is attached to a WebContents and will provide the @@ -132,10 +133,13 @@ // Returns a SecurityInfo describing an individual request for the // given |profile|. - static void SecurityInfoForRequest(const GURL& url, - const content::SSLStatus& ssl, - Profile* profile, - SecurityInfo* security_info); + static void SecurityInfoForRequest( + const GURL& url, + const content::SSLStatus& ssl, + Profile* profile, + const scoped_refptr<net::X509Certificate>& cert, + bool used_known_mitm_certificate, + SecurityInfo* security_info); private: explicit SecurityStateModel(content::WebContents* web_contents); @@ -151,6 +155,11 @@ mutable GURL visible_url_; mutable content::SSLStatus visible_ssl_status_; + // TODO(estark): The SecurityStateModel temporarily owns and + // instantiates this member, but it will soon be injected, once the + // model is compnentized. https://crbug.com/515071 + scoped_ptr<SecurityStateModelClient> client_; + DISALLOW_COPY_AND_ASSIGN(SecurityStateModel); };
diff --git a/chrome/browser/ssl/security_state_model_client.h b/chrome/browser/ssl/security_state_model_client.h new file mode 100644 index 0000000..61fd45878 --- /dev/null +++ b/chrome/browser/ssl/security_state_model_client.h
@@ -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. + +#ifndef CHROME_BROWSER_SSL_SECURITY_STATE_MODEL_CLIENT_H_ +#define CHROME_BROWSER_SSL_SECURITY_STATE_MODEL_CLIENT_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" + +namespace net { +class X509Certificate; +} // namespace net + +// Provides embedder-specific information that a SecurityStateModel +// needs to determine the page's security status. +class SecurityStateModelClient { + public: + SecurityStateModelClient() {} + virtual ~SecurityStateModelClient() {} + + // Returns the certificate used to load the page or request. + virtual bool RetrieveCert(scoped_refptr<net::X509Certificate>* cert) = 0; + + // Returns true if the page or request is known to be loaded with a + // certificate installed by the system administrator. + virtual bool UsedPolicyInstalledCertificate() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SecurityStateModelClient); +}; + +#endif // CHROME_BROWSER_SSL_SECURITY_STATE_MODEL_CLIENT_H_
diff --git a/chrome/browser/ssl/security_state_model_unittest.cc b/chrome/browser/ssl/security_state_model_unittest.cc index b8f15f8a..1086a96 100644 --- a/chrome/browser/ssl/security_state_model_unittest.cc +++ b/chrome/browser/ssl/security_state_model_unittest.cc
@@ -20,12 +20,14 @@ const char kUrl[] = "https://foo.test"; -void GetTestSSLStatus(int process_id, content::SSLStatus* ssl_status) { +void GetTestSSLStatus(int process_id, + scoped_refptr<net::X509Certificate>* cert, + content::SSLStatus* ssl_status) { content::CertStore* cert_store = content::CertStore::GetInstance(); - const scoped_refptr<net::X509Certificate>& cert = + *cert = net::ImportCertFromFile(net::GetTestCertsDirectory(), "sha1_2016.pem"); - ASSERT_TRUE(cert); - ssl_status->cert_id = cert_store->StoreCert(cert.get(), process_id); + ASSERT_TRUE(*cert); + ssl_status->cert_id = cert_store->StoreCert(cert->get(), process_id); EXPECT_GT(ssl_status->cert_id, 0); ssl_status->cert_status = net::CERT_STATUS_SHA1_SIGNATURE_PRESENT; ssl_status->security_bits = 256; @@ -42,9 +44,11 @@ Profile* test_profile = profile(); SecurityStateModel::SecurityInfo security_info; content::SSLStatus ssl_status; - ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status)); + scoped_refptr<net::X509Certificate> cert; + ASSERT_NO_FATAL_FAILURE( + GetTestSSLStatus(process()->GetID(), &cert, &ssl_status)); SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile, - &security_info); + cert, false, &security_info); EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_MINOR, security_info.sha1_deprecation_status); EXPECT_EQ(SecurityStateModel::NONE, security_info.security_level); @@ -57,10 +61,12 @@ Profile* test_profile = profile(); SecurityStateModel::SecurityInfo security_info; content::SSLStatus ssl_status; - ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status)); + scoped_refptr<net::X509Certificate> cert; + ASSERT_NO_FATAL_FAILURE( + GetTestSSLStatus(process()->GetID(), &cert, &ssl_status)); ssl_status.content_status = content::SSLStatus::DISPLAYED_INSECURE_CONTENT; SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile, - &security_info); + cert, false, &security_info); EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_MINOR, security_info.sha1_deprecation_status); EXPECT_EQ(SecurityStateModel::DISPLAYED_MIXED_CONTENT, @@ -70,7 +76,7 @@ ssl_status.security_style = content::SECURITY_STYLE_AUTHENTICATION_BROKEN; ssl_status.content_status = content::SSLStatus::RAN_INSECURE_CONTENT; SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile, - &security_info); + cert, false, &security_info); EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_MINOR, security_info.sha1_deprecation_status); EXPECT_EQ(SecurityStateModel::RAN_MIXED_CONTENT, @@ -85,11 +91,13 @@ Profile* test_profile = profile(); SecurityStateModel::SecurityInfo security_info; content::SSLStatus ssl_status; - ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status)); + scoped_refptr<net::X509Certificate> cert; + ASSERT_NO_FATAL_FAILURE( + GetTestSSLStatus(process()->GetID(), &cert, &ssl_status)); ssl_status.security_style = content::SECURITY_STYLE_AUTHENTICATION_BROKEN; ssl_status.cert_status |= net::CERT_STATUS_DATE_INVALID; SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile, - &security_info); + cert, false, &security_info); EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_MINOR, security_info.sha1_deprecation_status); EXPECT_EQ(SecurityStateModel::SECURITY_ERROR, security_info.security_level); @@ -102,7 +110,9 @@ Profile* test_profile = profile(); SecurityStateModel::SecurityInfo security_info; content::SSLStatus ssl_status; - ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status)); + scoped_refptr<net::X509Certificate> cert; + ASSERT_NO_FATAL_FAILURE( + GetTestSSLStatus(process()->GetID(), &cert, &ssl_status)); // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 from // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-4 const uint16 ciphersuite = 0xc02f; @@ -111,7 +121,7 @@ net::SSLConnectionStatusSetCipherSuite(ciphersuite, &ssl_status.connection_status); SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile, - &security_info); + cert, false, &security_info); EXPECT_TRUE(security_info.is_secure_protocol_and_ciphersuite); } @@ -120,7 +130,9 @@ Profile* test_profile = profile(); SecurityStateModel::SecurityInfo security_info; content::SSLStatus ssl_status; - ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status)); + scoped_refptr<net::X509Certificate> cert; + ASSERT_NO_FATAL_FAILURE( + GetTestSSLStatus(process()->GetID(), &cert, &ssl_status)); // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 from // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-4 const uint16 ciphersuite = 0xc02f; @@ -129,7 +141,7 @@ net::SSLConnectionStatusSetCipherSuite(ciphersuite, &ssl_status.connection_status); SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile, - &security_info); + cert, false, &security_info); EXPECT_FALSE(security_info.is_secure_protocol_and_ciphersuite); } @@ -138,7 +150,9 @@ Profile* test_profile = profile(); SecurityStateModel::SecurityInfo security_info; content::SSLStatus ssl_status; - ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status)); + scoped_refptr<net::X509Certificate> cert; + ASSERT_NO_FATAL_FAILURE( + GetTestSSLStatus(process()->GetID(), &cert, &ssl_status)); // TLS_RSA_WITH_AES_128_CCM_8 from // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-4 const uint16 ciphersuite = 0xc0a0; @@ -147,7 +161,7 @@ net::SSLConnectionStatusSetCipherSuite(ciphersuite, &ssl_status.connection_status); SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile, - &security_info); + cert, false, &security_info); EXPECT_FALSE(security_info.is_secure_protocol_and_ciphersuite); }
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc index d26a975..e750a9a 100644 --- a/chrome/browser/ssl/ssl_blocking_page.cc +++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -31,6 +31,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/google/core/browser/google_util.h" +#include "components/security_interstitials/core/controller_client.h" #include "components/ssl_errors/error_classification.h" #include "components/ssl_errors/error_info.h" #include "content/public/browser/browser_thread.h" @@ -314,30 +315,30 @@ bool retval = base::StringToInt(command, &cmd); DCHECK(retval); switch (cmd) { - case CMD_DONT_PROCEED: { + case security_interstitials::CMD_DONT_PROCEED: { interstitial_page()->DontProceed(); break; } - case CMD_PROCEED: { + case security_interstitials::CMD_PROCEED: { if (danger_overridable_) { interstitial_page()->Proceed(); } break; } - case CMD_DO_REPORT: { + case security_interstitials::CMD_DO_REPORT: { SetReportingPreference(true); break; } - case CMD_DONT_REPORT: { + case security_interstitials::CMD_DONT_REPORT: { SetReportingPreference(false); break; } - case CMD_SHOW_MORE_SECTION: { + case security_interstitials::CMD_SHOW_MORE_SECTION: { metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::SHOW_ADVANCED); break; } - case CMD_OPEN_HELP_CENTER: { + case security_interstitials::CMD_OPEN_HELP_CENTER: { metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::SHOW_LEARN_MORE); content::NavigationController::LoadURLParams help_page_params( @@ -346,18 +347,18 @@ web_contents()->GetController().LoadURLWithParams(help_page_params); break; } - case CMD_RELOAD: { + case security_interstitials::CMD_RELOAD: { metrics_helper()->RecordUserInteraction( security_interstitials::MetricsHelper::RELOAD); // The interstitial can't refresh itself. web_contents()->GetController().Reload(true); break; } - case CMD_OPEN_REPORTING_PRIVACY: + case security_interstitials::CMD_OPEN_REPORTING_PRIVACY: OpenExtendedReportingPrivacyPolicy(); break; - case CMD_OPEN_DATE_SETTINGS: - case CMD_OPEN_DIAGNOSTIC: + case security_interstitials::CMD_OPEN_DATE_SETTINGS: + case security_interstitials::CMD_OPEN_DIAGNOSTIC: // Commands not supported by the SSL interstitial. NOTREACHED() << "Unexpected command: " << command; }
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc index 1d7e7c8..a348065 100644 --- a/chrome/browser/ssl/ssl_browser_tests.cc +++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -46,6 +46,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/security_interstitials/core/controller_client.h" #include "components/security_interstitials/core/metrics_helper.h" #include "components/ssl_errors/error_classification.h" #include "components/variations/variations_associated_data.h" @@ -2319,9 +2320,9 @@ content::RenderViewHost* interstitial_rvh = interstitial_page->GetMainFrame()->GetRenderViewHost(); int result = -1; - std::string javascript = base::StringPrintf( - "window.domAutomationController.send(%d);", - SecurityInterstitialPage::CMD_PROCEED); + std::string javascript = + base::StringPrintf("window.domAutomationController.send(%d);", + security_interstitials::CMD_PROCEED); ASSERT_TRUE(content::ExecuteScriptAndExtractInt( interstitial_rvh, javascript, &result)); // The above will hang without the fix. @@ -2354,9 +2355,9 @@ content::RenderViewHost* interstitial_rvh = interstitial_page->GetMainFrame()->GetRenderViewHost(); int result = -1; - std::string javascript = base::StringPrintf( - "window.domAutomationController.send(%d);", - SecurityInterstitialPage::CMD_DONT_PROCEED); + std::string javascript = + base::StringPrintf("window.domAutomationController.send(%d);", + security_interstitials::CMD_DONT_PROCEED); ASSERT_TRUE(content::ExecuteScriptAndExtractInt( interstitial_rvh, javascript, &result)); // The above will hang without the fix.
diff --git a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc index 25e2fa5..8017928 100644 --- a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
@@ -163,7 +163,8 @@ } // TCM: 3705291 -IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, E2E_ENABLED(AddThenDelete)) { +// Disable as an E2E_Test: crbug.com/559250 +IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, AddThenDelete) { // Use a randomized URL to prevent test collisions. const base::string16 kHistoryUrl = ASCIIToUTF16(base::StringPrintf( "http://www.add-history.google.com/%s", base::GenerateGUID().c_str()));
diff --git a/chrome/browser/task_management/providers/child_process_task.cc b/chrome/browser/task_management/providers/child_process_task.cc index b5a8cb7..58d81c5 100644 --- a/chrome/browser/task_management/providers/child_process_task.cc +++ b/chrome/browser/task_management/providers/child_process_task.cc
@@ -6,7 +6,10 @@ #include "base/i18n/rtl.h" #include "base/numerics/safe_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/process_resource_usage.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/task_management/task_manager_observer.h" #include "chrome/grit/generated_resources.h" #include "components/nacl/common/nacl_process_type.h" @@ -15,6 +18,8 @@ #include "content/public/browser/child_process_data.h" #include "content/public/common/process_type.h" #include "content/public/common/service_registry.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/common/extension_set.h" #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -72,9 +77,26 @@ result_title); case PROCESS_TYPE_NACL_BROKER: return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX); - case PROCESS_TYPE_NACL_LOADER: + case PROCESS_TYPE_NACL_LOADER: { + auto* profile_manager = g_browser_process->profile_manager(); + if (profile_manager) { + // TODO(afakhry): Fix the below looping by plumbing a way to get the + // profile or the profile path from the child process host if any. + auto loaded_profiles = profile_manager->GetLoadedProfiles(); + for (auto* profile : loaded_profiles) { + auto& enabled_extensions = + extensions::ExtensionRegistry::Get(profile)->enabled_extensions(); + auto extension = + enabled_extensions.GetExtensionOrAppByURL(GURL(result_title)); + if (extension) { + result_title = base::UTF8ToUTF16(extension->name()); + break; + } + } + } return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NACL_PREFIX, result_title); + } // These types don't need display names or get them from elsewhere. case content::PROCESS_TYPE_BROWSER: case content::PROCESS_TYPE_RENDERER: @@ -127,6 +149,18 @@ return new ProcessResourceUsage(service.Pass()); } +bool UsesV8Memory(int process_type) { + switch (process_type) { + case content::PROCESS_TYPE_UTILITY: + case content::PROCESS_TYPE_BROWSER: + case content::PROCESS_TYPE_RENDERER: + return true; + + default: + return false; + } +} + } // namespace ChildProcessTask::ChildProcessTask(const content::ChildProcessData& data) @@ -137,7 +171,8 @@ v8_memory_allocated_(-1), v8_memory_used_(-1), unique_child_process_id_(data.id), - process_type_(data.process_type) { + process_type_(data.process_type), + uses_v8_memory_(UsesV8Memory(process_type_)) { } ChildProcessTask::~ChildProcessTask() { @@ -150,6 +185,9 @@ if ((refresh_flags & REFRESH_TYPE_V8_MEMORY) == 0) return; + if (!uses_v8_memory_) + return; + // The child process resources refresh is performed asynchronously, we will // invoke it and record the current values (which might be invalid at the // moment. We can safely ignore that and count on future refresh cycles @@ -190,7 +228,7 @@ } bool ChildProcessTask::ReportsV8Memory() const { - return process_resources_sampler_->ReportsV8MemoryStats(); + return uses_v8_memory_ && process_resources_sampler_->ReportsV8MemoryStats(); } int64 ChildProcessTask::GetV8MemoryAllocated() const {
diff --git a/chrome/browser/task_management/providers/child_process_task.h b/chrome/browser/task_management/providers/child_process_task.h index 9dc06e5..9160ec52 100644 --- a/chrome/browser/task_management/providers/child_process_task.h +++ b/chrome/browser/task_management/providers/child_process_task.h
@@ -51,6 +51,10 @@ // |NaClTrustedProcessType|. const int process_type_; + // Depending on the |process_type_|, determines whether this task uses V8 + // memory or not. + const bool uses_v8_memory_; + DISALLOW_COPY_AND_ASSIGN(ChildProcessTask); };
diff --git a/chrome/browser/task_management/providers/task.cc b/chrome/browser/task_management/providers/task.cc index 849fafd..025175d 100644 --- a/chrome/browser/task_management/providers/task.cc +++ b/chrome/browser/task_management/providers/task.cc
@@ -4,6 +4,10 @@ #include "chrome/browser/task_management/providers/task.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_info_cache.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/task_management/task_manager_observer.h" namespace task_management { @@ -31,6 +35,19 @@ Task::~Task() { } +// static +base::string16 Task::GetProfileNameFromProfile(Profile* profile) { + DCHECK(profile); + ProfileInfoCache& cache = + g_browser_process->profile_manager()->GetProfileInfoCache(); + size_t index = + cache.GetIndexOfProfileWithPath(profile->GetOriginalProfile()->GetPath()); + if (index != std::string::npos) + return cache.GetNameOfProfileAtIndex(index); + + return base::string16(); +} + void Task::Activate() { }
diff --git a/chrome/browser/task_management/providers/task.h b/chrome/browser/task_management/providers/task.h index 5fa551f..04732995 100644 --- a/chrome/browser/task_management/providers/task.h +++ b/chrome/browser/task_management/providers/task.h
@@ -12,6 +12,8 @@ #include "third_party/WebKit/public/web/WebCache.h" #include "ui/gfx/image/image_skia.h" +class Profile; + namespace task_management { // Defines a task that corresponds to a tab, an app, an extension, ... etc. It @@ -43,6 +45,9 @@ base::ProcessHandle handle); virtual ~Task(); + // Gets the name of the given |profile| from the ProfileInfoCache. + static base::string16 GetProfileNameFromProfile(Profile* profile); + // Activates this TaskManager's task by bringing its container to the front // (if possible). virtual void Activate(); @@ -69,8 +74,7 @@ // value is whatever unique IDs of their hosts in the browser process. virtual int GetChildProcessUniqueID() const = 0; - // The name of the profile associated with the browser context of the render - // view host that this task represents (if this task represents a renderer). + // The name of the profile owning this task. virtual base::string16 GetProfileName() const; // Getting the Sqlite used memory (in bytes). Not all tasks reports Sqlite
diff --git a/chrome/browser/task_management/providers/web_contents/renderer_task.cc b/chrome/browser/task_management/providers/web_contents/renderer_task.cc index 6b48475..67b6eca 100644 --- a/chrome/browser/task_management/providers/web_contents/renderer_task.cc +++ b/chrome/browser/task_management/providers/web_contents/renderer_task.cc
@@ -11,8 +11,6 @@ #include "chrome/browser/favicon/favicon_utils.h" #include "chrome/browser/process_resource_usage.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_info_cache.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/task_management/task_manager_observer.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/render_process_host.h" @@ -44,15 +42,7 @@ const content::RenderProcessHost* render_process_host) { Profile* profile = Profile::FromBrowserContext(render_process_host->GetBrowserContext()); - DCHECK(profile); - ProfileInfoCache& cache = - g_browser_process->profile_manager()->GetProfileInfoCache(); - size_t index = - cache.GetIndexOfProfileWithPath(profile->GetOriginalProfile()->GetPath()); - if (index != std::string::npos) - return cache.GetNameOfProfileAtIndex(index); - - return base::string16(); + return Task::GetProfileNameFromProfile(profile); } inline bool IsRendererResourceSamplingDisabled(int64 flags) {
diff --git a/chrome/browser/task_management/sampling/task_group.cc b/chrome/browser/task_management/sampling/task_group.cc index 45c596f..929d3b8d 100644 --- a/chrome/browser/task_management/sampling/task_group.cc +++ b/chrome/browser/task_management/sampling/task_group.cc
@@ -63,6 +63,7 @@ cpu_usage_(0.0), memory_usage_(), gpu_memory_(-1), + per_process_network_usage_(-1), #if defined(OS_WIN) gdi_current_handles_(-1), gdi_peak_handles_(-1), @@ -112,9 +113,18 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // First refresh the enabled non-expensive resources usages on the UI thread. - // 1- Refresh all the tasks. - for (auto& task_pair : tasks_) - task_pair.second->Refresh(update_interval, refresh_flags); + // 1- Refresh all the tasks as well as the total network usage (if enabled). + const bool network_usage_refresh_enabled = + IsResourceRefreshEnabled(REFRESH_TYPE_NETWORK_USAGE, refresh_flags); + per_process_network_usage_ = network_usage_refresh_enabled ? 0 : -1; + for (auto& task_pair : tasks_) { + Task* task = task_pair.second; + task->Refresh(update_interval, refresh_flags); + + if (network_usage_refresh_enabled && task->ReportsNetworkUsage()) { + per_process_network_usage_ += task->network_usage(); + } + } // 2- Refresh GPU memory (if enabled). if (IsResourceRefreshEnabled(REFRESH_TYPE_GPU_MEMORY, refresh_flags))
diff --git a/chrome/browser/task_management/sampling/task_group.h b/chrome/browser/task_management/sampling/task_group.h index 6f882d0..cca02a6 100644 --- a/chrome/browser/task_management/sampling/task_group.h +++ b/chrome/browser/task_management/sampling/task_group.h
@@ -54,6 +54,7 @@ int64 physical_bytes() const { return memory_usage_.physical_bytes; } int64 gpu_memory() const { return gpu_memory_; } bool gpu_memory_has_duplicates() const { return gpu_memory_has_duplicates_; } + int64 per_process_network_usage() const { return per_process_network_usage_; } #if defined(OS_WIN) int64 gdi_current_handles() const { return gdi_current_handles_; } @@ -97,6 +98,9 @@ double cpu_usage_; MemoryUsageStats memory_usage_; int64 gpu_memory_; + // The network usage in bytes per second as the sum of all network usages of + // the individual tasks sharing the same process. + int64 per_process_network_usage_; #if defined(OS_WIN) // Windows GDI and USER Handles. int64 gdi_current_handles_;
diff --git a/chrome/browser/task_management/sampling/task_manager_impl.cc b/chrome/browser/task_management/sampling/task_manager_impl.cc index 9779343..cb150dc 100644 --- a/chrome/browser/task_management/sampling/task_manager_impl.cc +++ b/chrome/browser/task_management/sampling/task_manager_impl.cc
@@ -92,7 +92,7 @@ #if !defined(DISABLE_NACL) return GetTaskGroupByTaskId(task_id)->nacl_debug_stub_port(); #else - return -1; + return -2; #endif // !defined(DISABLE_NACL) } @@ -151,6 +151,10 @@ return GetTaskByTaskId(task_id)->network_usage(); } +int64 TaskManagerImpl::GetProcessTotalNetworkUsage(TaskId task_id) const { + return GetTaskGroupByTaskId(task_id)->per_process_network_usage(); +} + int64 TaskManagerImpl::GetSqliteMemoryUsed(TaskId task_id) const { return GetTaskByTaskId(task_id)->GetSqliteMemoryUsed(); }
diff --git a/chrome/browser/task_management/sampling/task_manager_impl.h b/chrome/browser/task_management/sampling/task_manager_impl.h index 264aa45..89a2ed2 100644 --- a/chrome/browser/task_management/sampling/task_manager_impl.h +++ b/chrome/browser/task_management/sampling/task_manager_impl.h
@@ -51,6 +51,7 @@ const base::ProcessId& GetProcessId(TaskId task_id) const override; Task::Type GetType(TaskId task_id) const override; int64 GetNetworkUsage(TaskId task_id) const override; + int64 GetProcessTotalNetworkUsage(TaskId task_id) const override; int64 GetSqliteMemoryUsed(TaskId task_id) const override; bool GetV8Memory(TaskId task_id, int64* allocated,
diff --git a/chrome/browser/task_management/task_manager_interface.h b/chrome/browser/task_management/task_manager_interface.h index a58b7e7..9197785 100644 --- a/chrome/browser/task_management/task_manager_interface.h +++ b/chrome/browser/task_management/task_manager_interface.h
@@ -66,8 +66,9 @@ // refresh cycle. A value of -1 means no valid value is currently available. virtual int GetIdleWakeupsPerSecond(TaskId task_id) const = 0; - // Returns the NaCl GDB debug stub port. A value of -1 means no valid value is - // currently available. + // Returns the NaCl GDB debug stub port. A value of + // |nacl::kGdbDebugStubPortUnknown| means no valid value is currently + // available. A value of -2 means NaCl is not enabled for this build. virtual int GetNaClDebugStubPort(TaskId task_id) const = 0; // On Windows, gets the current and peak number of GDI and USER handles in @@ -104,6 +105,13 @@ // usage. virtual int64 GetNetworkUsage(TaskId task_id) const = 0; + // Returns the total network usage (in bytes per second) during the current + // refresh cycle for the process on which the task with |task_id| is running. + // This is the sum of all the network usage of the individual tasks (that + // can be gotten by the above GetNetworkUsage()). A value of -1 means network + // usage calculation refresh is currently not available. + virtual int64 GetProcessTotalNetworkUsage(TaskId task_id) const = 0; + // Returns the Sqlite used memory (in bytes) for the task with |task_id|. // A value of -1 means no valid value is currently available. virtual int64 GetSqliteMemoryUsed(TaskId task_id) const = 0;
diff --git a/chrome/browser/task_management/task_manager_observer_unittest.cc b/chrome/browser/task_management/task_manager_observer_unittest.cc index 80d308c8..296cbe2 100644 --- a/chrome/browser/task_management/task_manager_observer_unittest.cc +++ b/chrome/browser/task_management/task_manager_observer_unittest.cc
@@ -58,6 +58,9 @@ } Task::Type GetType(TaskId task_id) const override { return Task::UNKNOWN; } int64 GetNetworkUsage(TaskId task_id) const override { return -1; } + int64 GetProcessTotalNetworkUsage(TaskId task_id) const override { + return -1; + } int64 GetSqliteMemoryUsed(TaskId task_id) const override { return -1; } bool GetV8Memory(TaskId task_id, int64* allocated,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 6c1d26a8..b9e8c12 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -45,7 +45,6 @@ deps = [ # NOTE: New dependencies should generally be added in the OS!="ios" # dependencies block below, rather than here. - "//base/allocator", "//chrome:extra_resources", "//chrome:resources", "//chrome:strings",
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h index 2e375cd..dd9c7ef8 100644 --- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h +++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
@@ -79,7 +79,7 @@ content::WebContents* content); // Advance to the next item if an owned item is already active. The function - // will return true if it has sucessfully advanced. + // will return true if it has successfully advanced. bool AdvanceToNextApp(); // Returns true if the application is a V2 app.
diff --git a/chrome/browser/ui/cocoa/base_bubble_controller.mm b/chrome/browser/ui/cocoa/base_bubble_controller.mm index de526d8e..e63ba0e 100644 --- a/chrome/browser/ui/cocoa/base_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/base_bubble_controller.mm
@@ -210,7 +210,7 @@ base::scoped_nsobject<NSBox> spacer([[NSBox alloc] initWithFrame:frame]); [spacer setBoxType:NSBoxSeparator]; [spacer setBorderType:NSLineBorder]; - [spacer setAlphaValue:0.2]; + [spacer setAlphaValue:0.75]; return [spacer.release() autorelease]; } @@ -219,7 +219,7 @@ base::scoped_nsobject<NSBox> spacer([[NSBox alloc] initWithFrame:frame]); [spacer setBoxType:NSBoxSeparator]; [spacer setBorderType:NSLineBorder]; - [spacer setAlphaValue:0.2]; + [spacer setAlphaValue:0.75]; return [spacer.release() autorelease]; }
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm index d71ce4a..7554859 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.mm
@@ -418,10 +418,10 @@ // Make the button do something. [button setTarget:barController_]; [button setAction:@selector(openBookmark:)]; - // Add a tooltip. - [button setToolTip:[BookmarkMenuCocoaController tooltipForNode:node]]; [button setAcceptsTrackIn:YES]; } + // Add a tooltip. + [button setToolTip:[BookmarkMenuCocoaController tooltipForNode:node]]; } else { [button setEnabled:NO]; [button setBordered:NO];
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm index 203b6f8..078e7bf 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller_unittest.mm
@@ -241,16 +241,6 @@ EXPECT_TRUE(NSContainsRect(bigger, r)); EXPECT_TRUE([[button cell] isKindOfClass:cellClass]); } - - // Confirm folder buttons have no tooltip. The important thing - // really is that we insure folders and non-folders are treated - // differently; not sure of any other generic way to do this. - for (BookmarkButton* button in buttons) { - if ([button isFolder]) - EXPECT_FALSE([button toolTip]); - else - EXPECT_TRUE([button toolTip]); - } } // Make sure closing of the window releases the controller.
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm index 0a14142..5ce7822 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
@@ -43,6 +43,8 @@ + (NSString*)tooltipForNode:(const BookmarkNode*)node { NSString* title = base::SysUTF16ToNSString(node->GetTitle()); + if (node->is_folder()) + return title; std::string urlString = node->url().possibly_invalid_spec(); NSString* url = base::SysUTF8ToNSString(urlString); return cocoa_l10n_util::TooltipForURLAndTitle(url, title);
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index 43f633c4..9ba3f1bc 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/search/search_model_observer.h" +#include "chrome/browser/ui/tabs/tab_utils.h" #include "components/bookmarks/browser/bookmark_model.h" #include "ui/base/ui_base_types.h" @@ -180,9 +181,20 @@ // Adds the given FindBar cocoa controller to this browser window. void AddFindBar(FindBarCocoaController* find_bar_cocoa_controller); + // Update window media state to show if one of the tabs within the window is + // playing an audio/video or even if it's playing something but it's muted. + void UpdateMediaState(TabMediaState media_state); + // Returns the cocoa-world BrowserWindowController BrowserWindowController* cocoa_controller() { return controller_; } + // Returns window title based on the active tab title and window media state. + NSString* WindowTitle(); + + // Returns current media state, determined by the media state of tabs, set by + // UpdateMediaState. + TabMediaState media_state() { return media_state_; } + protected: void DestroyBrowser() override; @@ -194,6 +206,11 @@ base::scoped_nsobject<NSString> pending_window_title_; ui::WindowShowState initial_show_state_; NSInteger attention_request_id_; // identifier from requestUserAttention + + // Preserves window media state to show appropriate icon in the window title + // which can be audio playing, muting or none (determined by media state of + // tabs. + TabMediaState media_state_; }; #endif // CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_COCOA_H_
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 0c703069..dbace1df 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -297,13 +297,25 @@ } void BrowserWindowCocoa::UpdateTitleBar() { - NSString* newTitle = - base::SysUTF16ToNSString(browser_->GetWindowTitleForCurrentTab()); + NSString* newTitle = WindowTitle(); - pending_window_title_.reset( - [BrowserWindowUtils scheduleReplaceOldTitle:pending_window_title_.get() - withNewTitle:newTitle - forWindow:window()]); + pending_window_title_.reset([BrowserWindowUtils + scheduleReplaceOldTitle:pending_window_title_.get() + withNewTitle:newTitle + forWindow:window()]); +} + +NSString* BrowserWindowCocoa::WindowTitle() { + if (media_state_ == TAB_MEDIA_STATE_AUDIO_PLAYING) { + return l10n_util::GetNSStringF(IDS_WINDOW_AUDIO_PLAYING_MAC, + browser_->GetWindowTitleForCurrentTab(), + base::SysNSStringToUTF16(@"🔊")); + } else if (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING) { + return l10n_util::GetNSStringF(IDS_WINDOW_AUDIO_MUTING_MAC, + browser_->GetWindowTitleForCurrentTab(), + base::SysNSStringToUTF16(@"🔇")); + } + return base::SysUTF16ToNSString(browser_->GetWindowTitleForCurrentTab()); } void BrowserWindowCocoa::BookmarkBarStateChanged( @@ -550,6 +562,11 @@ [controller_ addFindBar:find_bar_cocoa_controller]; } +void BrowserWindowCocoa::UpdateMediaState(TabMediaState media_state) { + media_state_ = media_state; + UpdateTitleBar(); +} + void BrowserWindowCocoa::ShowUpdateChromeDialog() { restart_browser::RequestRestart(window()); }
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm b/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm index 3ff2a87..a55de3d3 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa_unittest.mm
@@ -11,11 +11,13 @@ #import "chrome/browser/ui/cocoa/browser_window_cocoa.h" #import "chrome/browser/ui/cocoa/browser_window_controller.h" #include "chrome/browser/ui/cocoa/cocoa_profile_test.h" +#include "chrome/grit/generated_resources.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_details.h" #include "testing/gtest/include/gtest/gtest.h" #import "third_party/ocmock/OCMock/OCMock.h" #import "third_party/ocmock/gtest_support.h" +#include "ui/base/l10n/l10n_util_mac.h" // Main test class. class BrowserWindowCocoaTest : public CocoaProfileTest { @@ -48,6 +50,28 @@ EXPECT_EQ(before, bwc->IsBookmarkBarVisible()); } +TEST_F(BrowserWindowCocoaTest, TestWindowTitle) { + scoped_ptr<BrowserWindowCocoa> bwc( + new BrowserWindowCocoa(browser(), controller_)); + NSString* playing_emoji = @"🔊"; + NSString* muting_emoji = @"🔇"; + EXPECT_EQ(static_cast<NSUInteger>(NSNotFound), + [bwc->WindowTitle() rangeOfString:playing_emoji].location); + EXPECT_EQ(static_cast<NSUInteger>(NSNotFound), + [bwc->WindowTitle() rangeOfString:muting_emoji].location); + bwc->UpdateMediaState(TAB_MEDIA_STATE_AUDIO_PLAYING); + EXPECT_NE(static_cast<NSUInteger>(NSNotFound), + [bwc->WindowTitle() rangeOfString:playing_emoji].location); + bwc->UpdateMediaState(TAB_MEDIA_STATE_AUDIO_MUTING); + EXPECT_NE(static_cast<NSUInteger>(NSNotFound), + [bwc->WindowTitle() rangeOfString:muting_emoji].location); + bwc->UpdateMediaState(TAB_MEDIA_STATE_NONE); + EXPECT_EQ(static_cast<NSUInteger>(NSNotFound), + [bwc->WindowTitle() rangeOfString:playing_emoji].location); + EXPECT_EQ(static_cast<NSUInteger>(NSNotFound), + [bwc->WindowTitle() rangeOfString:muting_emoji].location); +} + // Test that IsMaximized() returns false when the browser window goes from // maximized to minimized state - http://crbug/452976. TEST_F(BrowserWindowCocoaTest, TestMinimizeState) {
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h index d79d4f9..4195f72d 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.h +++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -15,6 +15,7 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/translate/chrome_translate_client.h" +#include "chrome/browser/ui/tabs/tab_utils.h" #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h" #import "chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.h" @@ -383,6 +384,13 @@ - (void)executeExtensionCommand:(const std::string&)extension_id command:(const extensions::Command&)command; +// To set whether the window has a tab playing audio or muted audio playing. +- (void)setMediaState:(TabMediaState)mediaState; + +// Returns current media state, determined by the media state of tabs, set by +// UpdateMediaState. +- (TabMediaState)mediaState; + @end // @interface BrowserWindowController
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index fbc7cfb..15e43a11 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1907,6 +1907,15 @@ command.accelerator()); } +- (void)setMediaState:(TabMediaState)mediaState { + static_cast<BrowserWindowCocoa*>([self browserWindow]) + ->UpdateMediaState(mediaState); +} + +- (TabMediaState)mediaState { + return static_cast<BrowserWindowCocoa*>([self browserWindow])->media_state(); +} + @end // @implementation BrowserWindowController @implementation BrowserWindowController(Fullscreen)
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h index b51e69a8..ad849bd 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
@@ -13,6 +13,7 @@ #import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h" #import "chrome/browser/ui/cocoa/url_drop_target.h" #include "chrome/browser/ui/tabs/hover_tab_selector.h" +#include "chrome/browser/ui/tabs/tab_utils.h" @class CrTrackingArea; @class CustomWindowControlsView; @@ -271,6 +272,20 @@ // Removes custom traffic light buttons from the tab strip. Idempotent. - (void)removeCustomWindowControls; +// Gets the tab and the media state to check whether the window +// media state should be updated or not. If the tab media state is +// AUDIO_PLAYING, the window media state should be set to AUDIO_PLAYING. +// If the tab media state is AUDIO_MUTING, this method would check if the +// window has no other tab with state AUDIO_PLAYING, then the window +// media state will be set to AUDIO_MUTING. If the tab media state is NONE, +// this method checks if the window has no playing or muting tab, then window +// media state will be set as NONE. +- (void)updateWindowMediaState:(TabMediaState)mediaState + forWebContents:(content::WebContents*)changed; + +// Returns the media state associated with the contents. +- (TabMediaState)mediaStateForContents:(content::WebContents*)contents; + @end @interface TabStripController(TestingAPI)
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm index 816aa1b3..6184e42b 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -45,7 +45,6 @@ #include "chrome/browser/ui/tabs/tab_menu_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" -#include "chrome/browser/ui/tabs/tab_utils.h" #include "chrome/common/chrome_switches.h" #include "chrome/grit/generated_resources.h" #include "components/metrics/proto/omnibox_event.pb.h" @@ -252,6 +251,8 @@ - (void)setNewTabButtonHoverState:(BOOL)showHover; - (void)themeDidChangeNotification:(NSNotification*)notification; - (void)setNewTabImages; +- (BOOL)doesAnyOtherWebContents:(content::WebContents*)selected + haveMediaState:(TabMediaState)state; @end // A simple view class that contains the traffic light buttons. This class @@ -1278,7 +1279,7 @@ [tab setTitle:base::SysUTF16ToNSString(title)]; const base::string16& toolTip = chrome::AssembleTabTooltipText( - title, chrome::GetTabMediaStateForContents(contents)); + title, [self mediaStateForContents:contents]); [tab setToolTip:base::SysUTF16ToNSString(toolTip)]; } @@ -1631,7 +1632,9 @@ } } - [tabController setMediaState:chrome::GetTabMediaStateForContents(contents)]; + TabMediaState mediaState = [self mediaStateForContents:contents]; + [self updateWindowMediaState:mediaState forWebContents:contents]; + [tabController setMediaState:mediaState]; [tabController updateVisibility]; } @@ -2296,6 +2299,60 @@ [customWindowControls_ setMouseInside:NO]; } +// Gets the tab and the media state to check whether the window +// media state should be updated or not. If the tab media state is +// AUDIO_PLAYING, the window media state should be set to AUDIO_PLAYING. +// If the tab media state is AUDIO_MUTING, this method would check if the +// window has no other tab with state AUDIO_PLAYING, then the window +// media state will be set to AUDIO_MUTING. If the tab media state is NONE, +// this method checks if the window has no playing or muting tab, then window +// media state will be set as NONE. +- (void)updateWindowMediaState:(TabMediaState)mediaState + forWebContents:(content::WebContents*)selected { + NSWindow* window = [tabStripView_ window]; + BrowserWindowController* windowController = + [BrowserWindowController browserWindowControllerForWindow:window]; + if (mediaState == TAB_MEDIA_STATE_NONE) { + if (![self doesAnyOtherWebContents:selected + haveMediaState:TAB_MEDIA_STATE_AUDIO_PLAYING] && + ![self doesAnyOtherWebContents:selected + haveMediaState:TAB_MEDIA_STATE_AUDIO_MUTING]) { + [windowController setMediaState:TAB_MEDIA_STATE_NONE]; + } else if ([self doesAnyOtherWebContents:selected + haveMediaState:TAB_MEDIA_STATE_AUDIO_MUTING]) { + [windowController setMediaState:TAB_MEDIA_STATE_AUDIO_MUTING]; + } + } else if (mediaState == TAB_MEDIA_STATE_AUDIO_MUTING) { + if (![self doesAnyOtherWebContents:selected + haveMediaState:TAB_MEDIA_STATE_AUDIO_PLAYING]) { + [windowController setMediaState:TAB_MEDIA_STATE_AUDIO_MUTING]; + } + } else { + [windowController setMediaState:mediaState]; + } +} + +// Checks if tabs (excluding selected) has media state equals to the second +// parameter. It returns YES when it finds the first tab with the criterion. +- (BOOL)doesAnyOtherWebContents:(content::WebContents*)selected + haveMediaState:(TabMediaState)state { + const int existingTabCount = tabStripModel_->count(); + for (int i = 0; i < existingTabCount; ++i) { + content::WebContents* currentContents = tabStripModel_->GetWebContentsAt(i); + if (selected == currentContents) + continue; + TabMediaState currentMediaStateForContents = + [self mediaStateForContents:currentContents]; + if (currentMediaStateForContents == state) + return YES; + } + return NO; +} + +- (TabMediaState)mediaStateForContents:(content::WebContents*)contents { + return chrome::GetTabMediaStateForContents(contents); +} + - (void)themeDidChangeNotification:(NSNotification*)notification { [self setNewTabImages]; }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm index cfe3a71..319d2431a 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller_unittest.mm
@@ -9,6 +9,7 @@ #include "chrome/browser/media/media_capture_devices_dispatcher.h" #include "chrome/browser/media/media_stream_capture_indicator.h" #include "chrome/browser/ui/browser_window.h" +#import "chrome/browser/ui/cocoa/browser_window_controller.h" #include "chrome/browser/ui/cocoa/cocoa_profile_test.h" #import "chrome/browser/ui/cocoa/new_tab_button.h" #import "chrome/browser/ui/cocoa/tabs/tab_controller.h" @@ -29,6 +30,25 @@ using content::SiteInstance; using content::WebContents; +@interface TabStripControllerForMediaTesting : TabStripController { + // Keeps media state of tabs in browser for testing purpose. + std::map<content::WebContents*, TabMediaState> contentsMediaStateMaps_; +} +@end + +@implementation TabStripControllerForMediaTesting +// Returns the media state of each tab from the map we are keeping. +- (TabMediaState)mediaStateForContents:(content::WebContents*)contents { + return contentsMediaStateMaps_[contents]; +} + +- (void)setMediaStateForContents:(content::WebContents*)contents + withMediaState:(TabMediaState)media_state { + contentsMediaStateMaps_[contents] = media_state; +} + +@end + @interface TestTabStripControllerDelegate : NSObject<TabStripControllerDelegate> { } @@ -102,7 +122,8 @@ NSRect switch_frame = NSMakeRect(0, 0, content_frame.size.width, 500); base::scoped_nsobject<NSView> switch_view( [[NSView alloc] initWithFrame:switch_frame]); - [parent addSubview:switch_view.get()]; + switch_view_ = switch_view; + [parent addSubview:switch_view_.get()]; // Create the tab strip view. It's expected to have a child button in it // already as the "new tab" button so create that too. @@ -135,6 +156,17 @@ CocoaProfileTest::TearDown(); } + // Return a derived TabStripController. + TabStripControllerForMediaTesting* InitTabStripControllerForMediaTesting() { + TabStripControllerForMediaTesting* c = + [[TabStripControllerForMediaTesting alloc] + initWithView:static_cast<TabStripView*>(tab_strip_.get()) + switchView:switch_view_.get() + browser:browser() + delegate:controller_delegate_.get()]; + return c; + } + TabView* CreateTab() { SiteInstance* instance = SiteInstance::Create(profile()); WebContents* web_contents = WebContents::Create( @@ -162,6 +194,7 @@ base::scoped_nsobject<TestTabStripControllerDelegate> controller_delegate_; base::scoped_nsobject<TabStripController> controller_; base::scoped_nsobject<TabStripView> tab_strip_; + base::scoped_nsobject<NSView> switch_view_; }; // Test adding and removing tabs and making sure that views get added to @@ -349,4 +382,89 @@ EXPECT_EQ(tab1, value); } +TEST_F(TabStripControllerTest, CorrectWindowFromUpdateWindowMediaState) { + controller_.reset(InitTabStripControllerForMediaTesting()); + NSWindow* window = [tab_strip_ window]; + BrowserWindowController* window_controller = + [BrowserWindowController browserWindowControllerForWindow:window]; + TabStripControllerForMediaTesting* tabStripControllerForTesting = + static_cast<TabStripControllerForMediaTesting*>(controller_); + + TabView* const tab1 = CreateTab(); + TabView* const tab2 = CreateTab(); + + // tab2 should be the selected one. + EXPECT_FALSE([tab1 controller].selected); + EXPECT_TRUE([tab2 controller].selected); + WebContents* const contents_at_tab1 = model_->GetActiveWebContents(); + + [tabStripControllerForTesting + setMediaStateForContents:contents_at_tab1 + withMediaState:TAB_MEDIA_STATE_AUDIO_PLAYING]; + // Make sure the overriden from base controller correctly handles media + // status of tabs. + EXPECT_EQ(TAB_MEDIA_STATE_AUDIO_PLAYING, + [controller_ mediaStateForContents:contents_at_tab1]); + [controller_ updateWindowMediaState:TAB_MEDIA_STATE_AUDIO_PLAYING + forWebContents:contents_at_tab1]; + // Because we have one tab playing, and the other one's media state is none, + // window media state should be AUDIO_PLAYING. + EXPECT_EQ(TAB_MEDIA_STATE_AUDIO_PLAYING, [window_controller mediaState]); + + model_->ActivateTabAt(0, false); + // tab1 should be the selected one now. + EXPECT_TRUE([tab1 controller].selected); + EXPECT_FALSE([tab2 controller].selected); + WebContents* const contents_at_tab0 = model_->GetActiveWebContents(); + + [tabStripControllerForTesting + setMediaStateForContents:contents_at_tab0 + withMediaState:TAB_MEDIA_STATE_AUDIO_MUTING]; + [controller_ updateWindowMediaState:TAB_MEDIA_STATE_AUDIO_MUTING + forWebContents:contents_at_tab0]; + // We have two tabs. One is playing and the other one is muting. The window + // media state should be still AUDIO_PLAYING. + EXPECT_EQ(TAB_MEDIA_STATE_AUDIO_PLAYING, [window_controller mediaState]); + + [tabStripControllerForTesting + setMediaStateForContents:contents_at_tab1 + withMediaState:TAB_MEDIA_STATE_AUDIO_MUTING]; + [controller_ updateWindowMediaState:TAB_MEDIA_STATE_AUDIO_MUTING + forWebContents:contents_at_tab1]; + // Now both tabs are muting, the window media state should be AUDIO_MUTING. + EXPECT_EQ(TAB_MEDIA_STATE_AUDIO_MUTING, [window_controller mediaState]); + + [tabStripControllerForTesting + setMediaStateForContents:contents_at_tab0 + withMediaState:TAB_MEDIA_STATE_AUDIO_PLAYING]; + [controller_ updateWindowMediaState:TAB_MEDIA_STATE_AUDIO_PLAYING + forWebContents:contents_at_tab0]; + // Among those tabs which were muting, one is started playing, the window + // media state should be playing. + EXPECT_EQ(TAB_MEDIA_STATE_AUDIO_PLAYING, [window_controller mediaState]); + + // Mute it again for further testing. + [tabStripControllerForTesting + setMediaStateForContents:contents_at_tab0 + withMediaState:TAB_MEDIA_STATE_AUDIO_MUTING]; + [controller_ updateWindowMediaState:TAB_MEDIA_STATE_AUDIO_MUTING + forWebContents:contents_at_tab0]; + + [tabStripControllerForTesting setMediaStateForContents:contents_at_tab1 + withMediaState:TAB_MEDIA_STATE_NONE]; + [controller_ updateWindowMediaState:TAB_MEDIA_STATE_NONE + forWebContents:contents_at_tab1]; + // One of the tabs is muting, the other one is none. So window media state + // should be MUTING. + EXPECT_EQ(TAB_MEDIA_STATE_AUDIO_MUTING, [window_controller mediaState]); + + [tabStripControllerForTesting setMediaStateForContents:contents_at_tab0 + withMediaState:TAB_MEDIA_STATE_NONE]; + [controller_ updateWindowMediaState:TAB_MEDIA_STATE_NONE + forWebContents:contents_at_tab0]; + // Neither of tabs playing nor muting, so the window media state should be + // NONE. + EXPECT_EQ(TAB_MEDIA_STATE_NONE, [window_controller mediaState]); +} + } // namespace
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc index 6037e40e..a1abf30 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -16,11 +16,11 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/passwords/passwords_model_delegate.h" -#include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "components/password_manager/core/browser/password_manager_constants.h" #include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/common/credential_manager_types.h" #include "components/password_manager/core/common/password_manager_ui.h" @@ -122,7 +122,7 @@ if (GetSmartLockBrandingState(GetProfile()) == password_bubble_experiment::SmartLockBranding::FULL) { std::string management_hostname = - GURL(chrome::kPasswordManagerAccountDashboardURL).host(); + GURL(password_manager::kPasswordManagerAccountDashboardURL).host(); save_confirmation_link = base::UTF8ToUTF16(management_hostname); confirmation_text_id = IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_SMART_LOCK_TEXT; @@ -315,7 +315,7 @@ switch (GetSmartLockBrandingState(GetProfile())) { case password_bubble_experiment::SmartLockBranding::FULL: PasswordsModelDelegateFromWebContents(web_contents()) - ->NavigateToSmartLockPage(); + ->NavigateToExternalPasswordManager(); break; case password_bubble_experiment::SmartLockBranding::SAVE_BUBBLE_ONLY: PasswordsModelDelegateFromWebContents(web_contents())
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc index b35b338..1cec681 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
@@ -83,7 +83,6 @@ MOCK_METHOD0(NavigateToPasswordManagerSettingsPage, void()); MOCK_METHOD0(NavigateToExternalPasswordManager, void()); - MOCK_METHOD0(NavigateToSmartLockPage, void()); MOCK_METHOD0(NavigateToSmartLockHelpPage, void()); MOCK_CONST_METHOD0(GetCurrentInteractionStats, password_manager::InteractionsStats*()); @@ -578,7 +577,7 @@ switch (test_case.expected_target) { case BrandLinkTarget::SMART_LOCK_HOME: - EXPECT_CALL(*controller(), NavigateToSmartLockPage()); + EXPECT_CALL(*controller(), NavigateToExternalPasswordManager()); break; case BrandLinkTarget::SMART_LOCK_HELP: EXPECT_CALL(*controller(), NavigateToSmartLockHelpPage());
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.cc b/chrome/browser/ui/passwords/manage_passwords_test.cc index 6551a75..feafe32 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.cc +++ b/chrome/browser/ui/passwords/manage_passwords_test.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" +#include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" @@ -19,7 +19,6 @@ #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" -#include "testing/gtest/include/gtest/gtest.h" ManagePasswordsTest::ManagePasswordsTest() { } @@ -101,7 +100,7 @@ return histogram_tester_.GetHistogramSamplesSinceCreation(histogram).Pass(); } -ManagePasswordsUIController* ManagePasswordsTest::GetController() { - return ManagePasswordsUIController::FromWebContents( +PasswordsClientUIDelegate* ManagePasswordsTest::GetController() { + return PasswordsClientUIDelegateFromWebContents( browser()->tab_strip_model()->GetActiveWebContents()); }
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.h b/chrome/browser/ui/passwords/manage_passwords_test.h index aee3613..a314213 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.h +++ b/chrome/browser/ui/passwords/manage_passwords_test.h
@@ -13,11 +13,10 @@ #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/common/credential_manager_types.h" #include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -class ManagePasswordsUIController; -class ManagePasswordsIconView; class GURL; +class ManagePasswordsIconView; +class PasswordsClientUIDelegate; // Test class for the various password management view bits and pieces. Sets // up a ManagePasswordsUIControllerMock, and provides some helper methods @@ -61,7 +60,7 @@ autofill::PasswordForm* test_form() { return &test_form_; } // Get the UI controller for the current WebContents. - ManagePasswordsUIController* GetController(); + PasswordsClientUIDelegate* GetController(); MOCK_METHOD1(OnChooseCredential, void(const password_manager::CredentialInfo&));
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index e348ec0..7cd4612 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -21,6 +21,7 @@ #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_form_manager.h" +#include "components/password_manager/core/browser/password_manager_constants.h" #include "components/password_manager/core/browser/statistics_table.h" #include "components/password_manager/core/common/credential_manager_types.h" #include "content/public/browser/navigation_details.h" @@ -71,40 +72,6 @@ ManagePasswordsUIController::~ManagePasswordsUIController() {} -void ManagePasswordsUIController::UpdateBubbleAndIconVisibility() { - // If we're not on a "webby" URL (e.g. "chrome://sign-in"), we shouldn't - // display either the bubble or the icon. - if (!BrowsingDataHelper::IsWebScheme( - web_contents()->GetLastCommittedURL().scheme())) { - passwords_data_.OnInactive(); - } - -#if !defined(OS_ANDROID) - Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); - if (!browser) - return; - LocationBar* location_bar = browser->window()->GetLocationBar(); - DCHECK(location_bar); - location_bar->UpdateManagePasswordsIconAndBubble(); -#endif -} - -void ManagePasswordsUIController:: - UpdateAndroidAccountChooserInfoBarVisibility() { -#if defined(OS_ANDROID) - // Deletes itself on the event from Java counterpart, when user interacts with - // dialog. - AccountChooserDialogAndroid* acccount_chooser_dialog = - new AccountChooserDialogAndroid(web_contents(), this); - acccount_chooser_dialog->ShowDialog(); - should_pop_up_bubble_ = false; -#endif -} - -base::TimeDelta ManagePasswordsUIController::Elapsed() const { - return timer_ ? timer_->Elapsed() : base::TimeDelta::Max(); -} - void ManagePasswordsUIController::OnPasswordSubmitted( scoped_ptr<PasswordFormManager> form_manager) { bool show_bubble = !form_manager->IsBlacklisted(); @@ -190,6 +157,20 @@ UpdateBubbleAndIconVisibility(); } +#if !defined(OS_ANDROID) +void ManagePasswordsUIController::UpdateIconAndBubbleState( + ManagePasswordsIconView* icon) { + if (should_pop_up_bubble_) { + // We must display the icon before showing the bubble, as the bubble would + // be otherwise unanchored. + icon->SetState(GetState()); + ShowBubbleWithoutUserInteraction(); + } else { + icon->SetState(GetState()); + } +} +#endif + const GURL& ManagePasswordsUIController::GetOrigin() const { return passwords_data_.origin(); } @@ -303,20 +284,7 @@ #else chrome::NavigateParams params( chrome::FindBrowserWithWebContents(web_contents()), - GURL(chrome::kPasswordManagerAccountDashboardURL), - ui::PAGE_TRANSITION_LINK); - params.disposition = NEW_FOREGROUND_TAB; - chrome::Navigate(¶ms); -#endif -} - -void ManagePasswordsUIController::NavigateToSmartLockPage() { -#if defined(OS_ANDROID) - NOTREACHED(); -#else - chrome::NavigateParams params( - chrome::FindBrowserWithWebContents(web_contents()), - GURL(l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK_PAGE)), + GURL(password_manager::kPasswordManagerAccountDashboardURL), ui::PAGE_TRANSITION_LINK); params.disposition = NEW_FOREGROUND_TAB; chrome::Navigate(¶ms); @@ -372,6 +340,28 @@ form_manager->PermanentlyBlacklist(); } +void ManagePasswordsUIController::UpdateBubbleAndIconVisibility() { + // If we're not on a "webby" URL (e.g. "chrome://sign-in"), we shouldn't + // display either the bubble or the icon. + if (!BrowsingDataHelper::IsWebScheme( + web_contents()->GetLastCommittedURL().scheme())) { + passwords_data_.OnInactive(); + } + +#if !defined(OS_ANDROID) + Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); + if (!browser) + return; + LocationBar* location_bar = browser->window()->GetLocationBar(); + DCHECK(location_bar); + location_bar->UpdateManagePasswordsIconAndBubble(); +#endif +} + +base::TimeDelta ManagePasswordsUIController::Elapsed() const { + return timer_ ? timer_->Elapsed() : base::TimeDelta::Max(); +} + void ManagePasswordsUIController::DidNavigateMainFrame( const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) { @@ -398,20 +388,6 @@ #endif } -#if !defined(OS_ANDROID) -void ManagePasswordsUIController::UpdateIconAndBubbleState( - ManagePasswordsIconView* icon) { - if (should_pop_up_bubble_) { - // We must display the icon before showing the bubble, as the bubble would - // be otherwise unanchored. - icon->SetState(GetState()); - ShowBubbleWithoutUserInteraction(); - } else { - icon->SetState(GetState()); - } -} -#endif - void ManagePasswordsUIController::ShowBubbleWithoutUserInteraction() { DCHECK(should_pop_up_bubble_); #if !defined(OS_ANDROID) @@ -430,3 +406,15 @@ if (password_store) password_store->RemoveObserver(this); } + +void ManagePasswordsUIController:: + UpdateAndroidAccountChooserInfoBarVisibility() { +#if defined(OS_ANDROID) + // Deletes itself on the event from Java counterpart, when user interacts with + // dialog. + AccountChooserDialogAndroid* acccount_chooser_dialog = + new AccountChooserDialogAndroid(web_contents(), this); + acccount_chooser_dialog->ShowDialog(); + should_pop_up_bubble_ = false; +#endif +}
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h index 373b818..0b993ad 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
@@ -5,13 +5,10 @@ #ifndef CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_H_ #define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_H_ -#include <vector> - -#include "base/memory/scoped_vector.h" #include "base/timer/elapsed_timer.h" #include "chrome/browser/ui/passwords/manage_passwords_state.h" +#include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h" #include "chrome/browser/ui/passwords/passwords_model_delegate.h" -#include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/password_store.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -34,50 +31,29 @@ : public content::WebContentsObserver, public content::WebContentsUserData<ManagePasswordsUIController>, public password_manager::PasswordStore::Observer, - public PasswordsModelDelegate { + public PasswordsModelDelegate, + public PasswordsClientUIDelegate { public: ~ManagePasswordsUIController() override; - // Called when the user submits a form containing login information, so we - // can handle later requests to save or blacklist that login information. - // This stores the provided object and triggers the UI to prompt the user - // about whether they would like to save the password. + // PasswordsClientUIDelegate: void OnPasswordSubmitted( - scoped_ptr<password_manager::PasswordFormManager> form_manager); - - // Called when the user submits a change password form, so we can handle - // later requests to update stored credentials in the PasswordManager. - // This stores the provided object and triggers the UI to prompt the user - // about whether they would like to update the password. + scoped_ptr<password_manager::PasswordFormManager> form_manager) override; void OnUpdatePasswordSubmitted( - scoped_ptr<password_manager::PasswordFormManager> form_manager); - - // Called when the site asks user to choose from credentials. This triggers - // the UI to prompt the user. |local_credentials| and |federated_credentials| - // shouldn't both be empty. + scoped_ptr<password_manager::PasswordFormManager> form_manager) override; bool OnChooseCredentials( ScopedVector<autofill::PasswordForm> local_credentials, ScopedVector<autofill::PasswordForm> federated_credentials, const GURL& origin, - base::Callback<void(const password_manager::CredentialInfo&)> callback); - - // Called when user is auto signed in to the site. |local_forms[0]| contains - // the credential returned to the site. - void OnAutoSignin(ScopedVector<autofill::PasswordForm> local_forms); - - // Called when the password will be saved automatically, but we still wish to - // visually inform the user that the save has occured. + base::Callback<void(const password_manager::CredentialInfo&)> callback) + override; + void OnAutoSignin(ScopedVector<autofill::PasswordForm> local_forms) override; void OnAutomaticPasswordSave( - scoped_ptr<password_manager::PasswordFormManager> form_manager); - - // Called when a form is autofilled with login information, so we can manage - // password credentials for the current site which are stored in - // |password_form_map|. This stores a copy of |password_form_map| and shows - // the manage password icon. + scoped_ptr<password_manager::PasswordFormManager> form_manager) override; void OnPasswordAutofilled(const autofill::PasswordFormMap& password_form_map, - const GURL& origin); + const GURL& origin) override; - // PasswordStore::Observer implementation. + // PasswordStore::Observer: void OnLoginsChanged( const password_manager::PasswordStoreChangeList& changes) override; @@ -110,10 +86,7 @@ void ChooseCredential( const autofill::PasswordForm& form, password_manager::CredentialType credential_type) override; - // Two different ways to open a new tab pointing to passwords.google.com. - // TODO(crbug.com/548259) eliminate one of them. void NavigateToExternalPasswordManager() override; - void NavigateToSmartLockPage() override; void NavigateToSmartLockHelpPage() override; void NavigateToPasswordManagerSettingsPage() override;
diff --git a/chrome/browser/ui/passwords/passwords_client_ui_delegate.cc b/chrome/browser/ui/passwords/passwords_client_ui_delegate.cc new file mode 100644 index 0000000..aaf92fd2 --- /dev/null +++ b/chrome/browser/ui/passwords/passwords_client_ui_delegate.cc
@@ -0,0 +1,13 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h" + +#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" + +PasswordsClientUIDelegate* PasswordsClientUIDelegateFromWebContents( + content::WebContents* web_contents) { + DCHECK(web_contents); + return ManagePasswordsUIController::FromWebContents(web_contents); +}
diff --git a/chrome/browser/ui/passwords/passwords_client_ui_delegate.h b/chrome/browser/ui/passwords/passwords_client_ui_delegate.h new file mode 100644 index 0000000..182e288 --- /dev/null +++ b/chrome/browser/ui/passwords/passwords_client_ui_delegate.h
@@ -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. + +#ifndef CHROME_BROWSER_UI_PASSWORDS_PASSWORDS_CLIENT_UI_DELEGATE_H_ +#define CHROME_BROWSER_UI_PASSWORDS_PASSWORDS_CLIENT_UI_DELEGATE_H_ + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "components/autofill/core/common/password_form.h" + +namespace content { +class WebContents; +} + +namespace password_manager { +struct CredentialInfo; +class PasswordFormManager; +} + +// An interface for ChromePasswordManagerClient implemented by +// ManagePasswordsUIController. Allows to push a new state for the tab. +class PasswordsClientUIDelegate { + public: + // Called when the user submits a form containing login information, so the + // later requests to save or blacklist can be handled. + // This stores the provided object and triggers the UI to prompt the user + // about whether they would like to save the password. + virtual void OnPasswordSubmitted( + scoped_ptr<password_manager::PasswordFormManager> form_manager) = 0; + + // Called when the user submits a new password for an existing credential. + // This stores the provided object and triggers the UI to prompt the user + // about whether they would like to update the password. + virtual void OnUpdatePasswordSubmitted( + scoped_ptr<password_manager::PasswordFormManager> form_manager) = 0; + + // Called when the site asks user to choose from credentials. This triggers + // the UI to prompt the user. |local_credentials| and |federated_credentials| + // shouldn't both be empty. + // Returns true when the UI is shown. |callback| is called when the user made + // a decision. If the UI isn't shown the method returns false and doesn't call + // |callback|. + virtual bool OnChooseCredentials( + ScopedVector<autofill::PasswordForm> local_credentials, + ScopedVector<autofill::PasswordForm> federated_credentials, + const GURL& origin, + base::Callback<void(const password_manager::CredentialInfo&)> + callback) = 0; + + // Called when user is auto signed in to the site. |local_forms[0]| contains + // the credential returned to the site. + virtual void OnAutoSignin( + ScopedVector<autofill::PasswordForm> local_forms) = 0; + + // Called when the password will be saved automatically, but we still wish to + // visually inform the user that the save has occured. + virtual void OnAutomaticPasswordSave( + scoped_ptr<password_manager::PasswordFormManager> form_manager) = 0; + + // Called when a form is autofilled with login information, so we can manage + // password credentials for the current site which are stored in + // |password_form_map|. This stores a copy of |password_form_map| and shows + // the manage password icon. + virtual void OnPasswordAutofilled( + const autofill::PasswordFormMap& password_form_map, + const GURL& origin) = 0; + + protected: + virtual ~PasswordsClientUIDelegate() = default; +}; + +// Returns ManagePasswordsUIController instance for |contents| +PasswordsClientUIDelegate* PasswordsClientUIDelegateFromWebContents( + content::WebContents* web_contents); + +#endif // CHROME_BROWSER_UI_PASSWORDS_PASSWORDS_CLIENT_UI_DELEGATE_H_
diff --git a/chrome/browser/ui/passwords/passwords_model_delegate.h b/chrome/browser/ui/passwords/passwords_model_delegate.h index c104c19..5226225 100644 --- a/chrome/browser/ui/passwords/passwords_model_delegate.h +++ b/chrome/browser/ui/passwords/passwords_model_delegate.h
@@ -80,10 +80,8 @@ const autofill::PasswordForm& form, password_manager::CredentialType credential_type) = 0; - // Two different ways to open a new tab pointing to passwords.google.com. - // TODO(crbug.com/548259) eliminate one of them. + // Open a new tab pointing to passwords.google.com. virtual void NavigateToExternalPasswordManager() = 0; - virtual void NavigateToSmartLockPage() = 0; // Open a new tab, pointing to the Smart Lock help article. virtual void NavigateToSmartLockHelpPage() = 0; // Open a new tab, pointing to the password manager settings page.
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc index 8767ed9..61e69066 100644 --- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc +++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -141,7 +141,7 @@ profile_sync_service->SetSetupInProgress(true); // Make sure the syncing is requested, otherwise the SigninManager - // will not be able to complete sucessfully. + // will not be able to complete successfully. sync_driver::SyncPrefs sync_prefs(profile_->GetPrefs()); sync_prefs.SetSyncRequested(true); }
diff --git a/chrome/browser/ui/task_manager/task_manager_table_model.cc b/chrome/browser/ui/task_manager/task_manager_table_model.cc index 90f88652..877f705 100644 --- a/chrome/browser/ui/task_manager/task_manager_table_model.cc +++ b/chrome/browser/ui/task_manager/task_manager_table_model.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/task_manager/task_manager_table_model.h" +#include "base/command_line.h" #include "base/i18n/number_formatting.h" #include "base/i18n/rtl.h" #include "base/prefs/scoped_user_pref_update.h" @@ -17,6 +18,7 @@ #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/nacl/browser/nacl_browser.h" +#include "components/nacl/common/nacl_switches.h" #include "content/public/common/result_codes.h" #include "third_party/WebKit/public/web/WebCache.h" #include "ui/base/l10n/l10n_util.h" @@ -47,6 +49,7 @@ case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: case IDS_TASK_MANAGER_CPU_COLUMN: + case IDS_TASK_MANAGER_NET_COLUMN: case IDS_TASK_MANAGER_PROCESS_ID_COLUMN: case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: @@ -55,6 +58,7 @@ case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN: case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN: + case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN: return true; default: return false; @@ -87,7 +91,9 @@ zero_string_(base::ASCIIToUTF16("0")), asterisk_string_(base::ASCIIToUTF16("*")), unknown_string_(l10n_util::GetStringUTF16( - IDS_TASK_MANAGER_UNKNOWN_VALUE_TEXT)) { + IDS_TASK_MANAGER_UNKNOWN_VALUE_TEXT)), + disabled_nacl_debugging_string_(l10n_util::GetStringUTF16( + IDS_TASK_MANAGER_DISABLED_NACL_DBG_TEXT)) { } ~TaskManagerValuesStringifier() {} @@ -128,7 +134,7 @@ } base::string16 GetNaClPortText(int nacl_port) { - if (nacl_port == nacl::kGdbDebugStubPortUnused) + if (nacl_port == nacl::kGdbDebugStubPortUnused || nacl_port == -2) return n_a_string_; if (nacl_port == nacl::kGdbDebugStubPortUnknown) @@ -175,6 +181,9 @@ const base::string16& zero_string() const { return zero_string_; } const base::string16& asterisk_string() const { return asterisk_string_; } const base::string16& unknown_string() const { return unknown_string_; } + const base::string16& disabled_nacl_debugging_string() const { + return disabled_nacl_debugging_string_; + } private: // The localized string "N/A". @@ -190,6 +199,10 @@ // The string "Unknown". const base::string16 unknown_string_; + // The string to show on the NaCl debug port column cells when the flag + // #enable-nacl-debug is disabled. + const base::string16 disabled_nacl_debugging_string_; + DISALLOW_COPY_AND_ASSIGN(TaskManagerValuesStringifier); }; @@ -218,7 +231,13 @@ table_view_delegate_(delegate), columns_settings_(new base::DictionaryValue), table_model_observer_(nullptr), - stringifier_(new TaskManagerValuesStringifier) { + stringifier_(new TaskManagerValuesStringifier), +#if !defined(DISABLE_NACL) + is_nacl_debugging_flag_enabled_(base::CommandLine::ForCurrentProcess()-> + HasSwitch(switches::kEnableNaClDebug)) { +#else + is_nacl_debugging_flag_enabled_(false) { +#endif // !defined(DISABLE_NACL) DCHECK(delegate); } @@ -242,7 +261,7 @@ case IDS_TASK_MANAGER_NET_COLUMN: return stringifier_->GetNetworkUsageText( - observed_task_manager()->GetNetworkUsage(tasks_[row])); + observed_task_manager()->GetProcessTotalNetworkUsage(tasks_[row])); case IDS_TASK_MANAGER_CPU_COLUMN: return stringifier_->GetCpuUsageText( @@ -325,6 +344,9 @@ } case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN: + if (!is_nacl_debugging_flag_enabled_) + return stringifier_->disabled_nacl_debugging_string(); + return stringifier_->GetNaClPortText( observed_task_manager()->GetNaClDebugStubPort(tasks_[row]));
diff --git a/chrome/browser/ui/task_manager/task_manager_table_model.h b/chrome/browser/ui/task_manager/task_manager_table_model.h index 687803b..ef51a00 100644 --- a/chrome/browser/ui/task_manager/task_manager_table_model.h +++ b/chrome/browser/ui/task_manager/task_manager_table_model.h
@@ -131,6 +131,9 @@ // values to string16. scoped_ptr<TaskManagerValuesStringifier> stringifier_; + // The status of the flag #enable-nacl-debug. + bool is_nacl_debugging_flag_enabled_; + DISALLOW_COPY_AND_ASSIGN(TaskManagerTableModel); };
diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc index f7637f9..52534d80 100644 --- a/chrome/browser/ui/views/chrome_views_delegate.cc +++ b/chrome/browser/ui/views/chrome_views_delegate.cc
@@ -64,7 +64,6 @@ #include "chrome/browser/ui/ash/ash_util.h" #endif - // Helpers -------------------------------------------------------------------- namespace { @@ -94,6 +93,7 @@ #if defined(OS_WIN) bool MonitorHasTopmostAutohideTaskbarForEdge(UINT edge, HMONITOR monitor) { APPBARDATA taskbar_data = { sizeof(APPBARDATA), NULL, 0, edge }; + taskbar_data.hWnd = ::GetForegroundWindow(); // TODO(robliao): Remove ScopedTracker below once crbug.com/462368 is fixed. tracked_objects::ScopedTracker tracking_profile( @@ -105,12 +105,31 @@ // idea for multi-monitor systems. Unfortunately, it appears to not work at // least some of the time (erroneously returning NULL) and there's almost no // online documentation or other sample code using it that suggests ways to - // address this problem. So we just use ABM_GETAUTOHIDEBAR and hope the user - // only cares about autohide bars on the monitor with the primary taskbar. - // + // address this problem. We do the following:- + // 1. Use the ABM_GETAUTOHIDEBAR message. If it works, i.e. returns a valid + // window we are done. + // 2. If the ABM_GETAUTOHIDEBAR message does not work we query the auto hide + // state of the taskbar and then retrieve its position. That call returns + // the edge on which the taskbar is present. If it matches the edge we + // are looking for, we are done. // NOTE: This call spins a nested message loop. HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR, &taskbar_data)); + if (!::IsWindow(taskbar)) { + APPBARDATA taskbar_data = { sizeof(APPBARDATA), 0, 0, 0}; + unsigned int taskbar_state = SHAppBarMessage(ABM_GETSTATE, + &taskbar_data); + if (!(taskbar_state & ABS_AUTOHIDE)) + return false; + + taskbar_data.hWnd = ::FindWindow(L"Shell_TrayWnd", NULL); + if (!::IsWindow(taskbar_data.hWnd)) + return false; + + SHAppBarMessage(ABM_GETTASKBARPOS, &taskbar_data); + if (taskbar_data.uEdge == edge) + taskbar = taskbar_data.hWnd; + } return ::IsWindow(taskbar) && (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) && (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST); @@ -354,6 +373,11 @@ } } #endif // OS_WIN + + if (!use_non_toplevel_window && !native_widget_factory().is_null()) { + params->native_widget = native_widget_factory().Run(*params, delegate); + return; + } #endif // USE_AURA #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc index 81170e0..7f4401f 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc
@@ -217,8 +217,13 @@ metrics_util::MANUAL_MANAGE_PASSWORDS)); } -// If this flakes, disable and log details in http://crbug.com/523255. -IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, CloseOnClick) { +// Flaky on Windows (http://crbug.com/523255). +#if defined(OS_WIN) +#define MAYBE_CloseOnClick DISABLED_CloseOnClick +#else +#define MAYBE_CloseOnClick CloseOnClick +#endif +IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, MAYBE_CloseOnClick) { SetupPendingPassword(); EXPECT_TRUE(IsBubbleShowing()); EXPECT_FALSE(ManagePasswordsBubbleView::manage_password_bubble()->
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index 16412db0..31cfab30 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -558,7 +558,7 @@ // CanvasImageSource: void Draw(gfx::Canvas* canvas) override { - const SkISize size = canvas->sk_canvas()->getDeviceSize(); + const SkISize size = canvas->sk_canvas()->getBaseLayerSize(); gfx::Rect bounds(0, 0, size.width(), size.height()); SkPaint paint;
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 a158275..ef288e4a 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -449,30 +449,16 @@ const std::string& gaia_id) const { const std::string canonicalized_email = gaia::CanonicalizeEmail(gaia::SanitizeEmail(authenticated_email)); - const AccountId authenticated_account_id( - AccountId::FromUserEmailGaiaId(canonicalized_email, gaia_id)); - // If we don't have UserManager instance (i.e. we are in unit test), - // or a known user has authenticated, just log in. - user_manager::UserManager* user_manager = user_manager::UserManager::Get(); - if (!user_manager || user_manager->IsKnownUser(authenticated_account_id)) - return authenticated_account_id; + const AccountId account_id = user_manager::UserManager::GetKnownUserAccountId( + authenticated_email, gaia_id); - // If [part of] user id has changed, update stored data and connect user - // to existing home directory. - AccountId old_account_id(EmptyAccountId()); - if (!user_manager->GetKnownUserAccountId(authenticated_account_id, - &old_account_id)) { - return authenticated_account_id; - } - - if (old_account_id.GetUserEmail() != canonicalized_email) { - LOG(WARNING) << "Existing user '" << old_account_id.GetUserEmail() + if (account_id.GetUserEmail() != canonicalized_email) { + LOG(WARNING) << "Existing user '" << account_id.GetUserEmail() << "' authenticated by alias '" << canonicalized_email << "'."; - return old_account_id; } - return authenticated_account_id; + return account_id; } void GaiaScreenHandler::HandleCompleteAuthentication(
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 73ee81e..a1f1a722 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -865,9 +865,9 @@ core_oobe_actor_->RefocusCurrentPod(); } -void SigninScreenHandler::OnUserRemoved(const std::string& username, +void SigninScreenHandler::OnUserRemoved(const AccountId& account_id, bool last_user_removed) { - CallJS("login.AccountPickerScreen.removeUser", username); + CallJS("login.AccountPickerScreen.removeUser", account_id); if (last_user_removed) OnShowAddUser(); } @@ -1061,7 +1061,7 @@ if (!delegate_) return; - delegate_->RemoveUser(account_id.GetUserEmail()); + delegate_->RemoveUser(account_id); UpdateAddButtonStatus(); }
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 0f5b3f02..853fb564 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -35,6 +35,7 @@ #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/events/event_handler.h" +class AccountId; class EasyUnlockService; namespace base { @@ -77,7 +78,7 @@ public: virtual void ClearAndEnablePassword() = 0; virtual void ClearUserPodPassword() = 0; - virtual void OnUserRemoved(const std::string& username, + virtual void OnUserRemoved(const AccountId& account_id, bool last_user_removed) = 0; virtual void OnUserImageChanged(const user_manager::User& user) = 0; virtual void OnPreferencesChanged() = 0; @@ -166,7 +167,7 @@ virtual void LoadSigninWallpaper() = 0; // Attempts to remove given user. - virtual void RemoveUser(const std::string& username) = 0; + virtual void RemoveUser(const AccountId& account_id) = 0; // Let the delegate know about the handler it is supposed to be using. virtual void SetWebUIHandler(LoginDisplayWebUIHandler* webui_handler) = 0; @@ -285,7 +286,7 @@ // LoginDisplayWebUIHandler implementation: void ClearAndEnablePassword() override; void ClearUserPodPassword() override; - void OnUserRemoved(const std::string& username, + void OnUserRemoved(const AccountId& account_id, bool last_user_removed) override; void OnUserImageChanged(const user_manager::User& user) override; void OnPreferencesChanged() override;
diff --git a/chrome/browser/ui/webui/flags_ui.cc b/chrome/browser/ui/webui/flags_ui.cc index ceed341..bd26150 100644 --- a/chrome/browser/ui/webui/flags_ui.cc +++ b/chrome/browser/ui/webui/flags_ui.cc
@@ -112,7 +112,7 @@ // The handler for Javascript messages for the about:flags page. class FlagsDOMHandler : public WebUIMessageHandler { public: - FlagsDOMHandler() : access_(about_flags::kGeneralAccessFlagsOnly), + FlagsDOMHandler() : access_(flags_ui::kGeneralAccessFlagsOnly), experimental_features_requested_(false) { } ~FlagsDOMHandler() override {} @@ -121,7 +121,7 @@ // access. If there were flags experiments requested from javascript before // this was called, it calls |HandleRequestExperimentalFeatures| again. void Init(flags_ui::FlagsStorage* flags_storage, - about_flags::FlagAccess access); + flags_ui::FlagAccess access); // WebUIMessageHandler implementation. void RegisterMessages() override; @@ -140,7 +140,7 @@ private: scoped_ptr<flags_ui::FlagsStorage> flags_storage_; - about_flags::FlagAccess access_; + flags_ui::FlagAccess access_; bool experimental_features_requested_; DISALLOW_COPY_AND_ASSIGN(FlagsDOMHandler); @@ -166,7 +166,7 @@ } void FlagsDOMHandler::Init(flags_ui::FlagsStorage* flags_storage, - about_flags::FlagAccess access) { + flags_ui::FlagAccess access) { flags_storage_.reset(flags_storage); access_ = access; @@ -195,7 +195,7 @@ results.SetBoolean(flags_ui::kNeedsRestart, about_flags::IsRestartNeededToCommitChanges()); results.SetBoolean(flags_ui::kShowOwnerWarning, - access_ == about_flags::kGeneralAccessFlagsOnly); + access_ == flags_ui::kGeneralAccessFlagsOnly); #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) version_info::Channel channel = chrome::GetChannel(); @@ -236,7 +236,7 @@ base::CommandLine user_flags(base::CommandLine::NO_PROGRAM); about_flags::ConvertFlagsToSwitches(flags_storage_.get(), &user_flags, - about_flags::kAddSentinels); + flags_ui::kAddSentinels); base::CommandLine::StringVector flags; // argv[0] is the program name |base::CommandLine::NO_PROGRAM|. flags.assign(user_flags.argv().begin() + 1, user_flags.argv().end()); @@ -278,11 +278,11 @@ profile); dom_handler->Init(new chromeos::about_flags::OwnerFlagsStorage( profile->GetPrefs(), service), - about_flags::kOwnerAccessToFlags); + flags_ui::kOwnerAccessToFlags); } else { dom_handler->Init( new flags_ui::PrefServiceFlagsStorage(profile->GetPrefs()), - about_flags::kGeneralAccessFlagsOnly); + flags_ui::kGeneralAccessFlagsOnly); } } #endif @@ -319,7 +319,7 @@ #else handler->Init( new flags_ui::PrefServiceFlagsStorage(g_browser_process->local_state()), - about_flags::kOwnerAccessToFlags); + flags_ui::kOwnerAccessToFlags); #endif // Set up the about:flags source.
diff --git a/chrome/browser/ui/webui/options/password_manager_handler.cc b/chrome/browser/ui/webui/options/password_manager_handler.cc index 23055dd..7523e5cc 100644 --- a/chrome/browser/ui/webui/options/password_manager_handler.cc +++ b/chrome/browser/ui/webui/options/password_manager_handler.cc
@@ -20,6 +20,7 @@ #include "components/autofill/core/common/password_form.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "components/password_manager/core/browser/password_manager_constants.h" #include "components/password_manager/core/browser/password_ui_utils.h" #include "components/password_manager/core/common/experiments.h" #include "components/url_formatter/url_formatter.h" @@ -111,11 +112,12 @@ localized_strings->SetString("passwordManagerLearnMoreURL", chrome::kPasswordManagerLearnMoreURL); - localized_strings->SetString("passwordsManagePasswordsLink", - chrome::kPasswordManagerAccountDashboardURL); + localized_strings->SetString( + "passwordsManagePasswordsLink", + password_manager::kPasswordManagerAccountDashboardURL); std::string management_hostname = - GURL(chrome::kPasswordManagerAccountDashboardURL).host(); + GURL(password_manager::kPasswordManagerAccountDashboardURL).host(); base::string16 link_text = base::UTF8ToUTF16(management_hostname); size_t offset; base::string16 full_text = l10n_util::GetStringFUTF16(
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index e4018c2..cba3bcc 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -573,6 +573,8 @@ 'browser/interests/interests_fetcher.h', 'browser/internal_auth.cc', 'browser/internal_auth.h', + 'browser/interstitials/chrome_controller_client.cc', + 'browser/interstitials/chrome_controller_client.h', 'browser/interstitials/chrome_metrics_helper.cc', 'browser/interstitials/chrome_metrics_helper.h', 'browser/interstitials/security_interstitial_page.cc', @@ -1142,6 +1144,7 @@ 'browser/importer/profile_writer.h', 'browser/lifetime/browser_close_manager.cc', 'browser/lifetime/browser_close_manager.h', + 'browser/media_galleries/android/mtp_device_delegate_impl_android.cc', 'browser/media_galleries/fileapi/av_scanning_file_validator.cc', 'browser/media_galleries/fileapi/av_scanning_file_validator.h', 'browser/media_galleries/fileapi/device_media_async_file_util.cc', @@ -2779,6 +2782,8 @@ 'browser/ssl/bad_clock_blocking_page.h', 'browser/ssl/cert_report_helper.cc', 'browser/ssl/cert_report_helper.h', + 'browser/ssl/chrome_security_state_model_client.cc', + 'browser/ssl/chrome_security_state_model_client.h', 'browser/ssl/chrome_ssl_host_state_delegate.cc', 'browser/ssl/chrome_ssl_host_state_delegate.h', 'browser/ssl/chrome_ssl_host_state_delegate_factory.cc', @@ -2789,6 +2794,7 @@ 'browser/ssl/security_state_model.h', 'browser/ssl/security_state_model_android.cc', 'browser/ssl/security_state_model_android.h', + 'browser/ssl/security_state_model_client.h', 'browser/ssl/ssl_blocking_page.cc', 'browser/ssl/ssl_blocking_page.h', 'browser/ssl/ssl_cert_reporter.h', @@ -3757,11 +3763,6 @@ 'kasko_dll', ], }], - ['win_use_allocator_shim==1', { - 'dependencies': [ - '<(allocator_target)', - ], - }], ['branding!="Chrome"', { 'dependencies!': [ '../google_update/google_update.gyp:google_update',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 0f232530..8c0ca4fa 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi
@@ -1097,13 +1097,6 @@ '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2', '../third_party/isimpledom/isimpledom.gyp:isimpledom', ], - 'conditions': [ - ['win_use_allocator_shim==1', { - 'dependencies': [ - '<(allocator_target)', - ], - }], - ], }, { # 'OS!="win" 'conditions': [ ['OS=="linux" and toolkit_views==1',{
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index a92b49b6..ea876ed 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -118,6 +118,8 @@ 'browser/ui/passwords/manage_passwords_ui_controller.h', 'browser/ui/passwords/manage_passwords_view_utils.cc', 'browser/ui/passwords/manage_passwords_view_utils.h', + 'browser/ui/passwords/passwords_client_ui_delegate.cc', + 'browser/ui/passwords/passwords_client_ui_delegate.h', 'browser/ui/passwords/passwords_model_delegate.cc', 'browser/ui/passwords/passwords_model_delegate.h', 'browser/ui/passwords/password_manager_presenter.cc', @@ -3134,11 +3136,6 @@ 'browser/ui/views/frame/taskbar_decorator.cc' ], 'conditions': [ - ['win_use_allocator_shim==1', { - 'dependencies': [ - '<(allocator_target)', - ], - }], ['branding!="Chrome"', { 'dependencies!': [ '../google_update/google_update.gyp:google_update',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 6694cca..1438853 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi
@@ -329,7 +329,9 @@ '<(DEPTH)/components/components.gyp:component_updater', '<(DEPTH)/components/components.gyp:content_settings_core_common', '<(DEPTH)/components/components.gyp:crash_core_common', + '<(DEPTH)/components/components.gyp:error_page_common', '<(DEPTH)/components/components.gyp:favicon_base', + '<(DEPTH)/components/components.gyp:flags_ui_switches', '<(DEPTH)/components/components.gyp:gcm_driver_common', '<(DEPTH)/components/components.gyp:json_schema', '<(DEPTH)/components/components.gyp:metrics',
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi index 67f9b1b..0ea9690 100644 --- a/chrome/chrome_dll.gypi +++ b/chrome/chrome_dll.gypi
@@ -366,6 +366,11 @@ 'app/close_handle_hook_win.h', ], 'conditions': [ + ['OS=="win" and win_use_allocator_shim==1', { + 'dependencies': [ + '<(allocator_target)', + ], + }], ['OS=="win"', { 'conditions': [ ['chrome_pgo_phase==1', {
diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index d02673f..f593901 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi
@@ -421,6 +421,7 @@ '../chrome_elf/chrome_elf.gyp:chrome_elf', '../components/components.gyp:crash_component', '../components/components.gyp:crash_core_common', + '../components/components.gyp:flags_ui_switches', '../sandbox/sandbox.gyp:sandbox', '../ui/gfx/gfx.gyp:gfx', '../win8/metro_driver/metro_driver.gyp:metro_driver', @@ -552,6 +553,7 @@ '../breakpad/breakpad.gyp:breakpad_sender_win64', '../components/components.gyp:breakpad_win64', '../components/components.gyp:crash_core_common_win64', + '../components/components.gyp:flags_ui_switches_win64', '../chrome/common_constants.gyp:common_constants_win64', '../components/nacl.gyp:nacl_win64', '../crypto/crypto.gyp:crypto_nacl_win64',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index b4d1dcf..b12ac525 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi
@@ -391,16 +391,6 @@ 'include_dirs': [ '<(DEPTH)/third_party/wtl/include', ], - 'conditions': [ - ['win_use_allocator_shim==1', { - 'dependencies': [ - '<(allocator_target)', - ], - 'export_dependent_settings': [ - '<(allocator_target)', - ], - }], - ], }], ], },
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 1f6ebff..fb2bf38 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -2814,6 +2814,7 @@ '<@(chromium_browser_dependencies)', '<@(chromium_child_dependencies)', '../components/components.gyp:crash_core_common', + '../components/components.gyp:flags_ui_switches', '../content/content.gyp:content_app_both', # 2) test-specific support libraries: '../base/base.gyp:run_all_unittests',
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 21cf8d8..bc89196 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -66,6 +66,7 @@ "//components/dom_distiller/core", "//components/error_page/common", "//components/favicon_base", + "//components/flags_ui:switches", "//components/gcm_driver/common", "//components/json_schema", "//components/metrics",
diff --git a/chrome/common/DEPS b/chrome/common/DEPS index 5c419a4..b39de13 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS
@@ -11,6 +11,7 @@ "+components/data_reduction_proxy/content/common", "+components/data_reduction_proxy/core/common", "+components/dom_distiller/core", + "+components/flags_ui/flags_ui_switches.h", "+components/gcm_driver", "+components/metrics/client_info.h", "+components/metrics/metrics_pref_names.h",
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 90584bb7..c4f324d 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -572,12 +572,6 @@ // loaded. It is useful to tell the difference for tracking purposes. const char kFastStart[] = "fast-start"; -// These two flags are added around the switches about:flags adds to the -// command line. This is useful to see which switches were added by about:flags -// on about:version. They don't have any effect. -const char kFlagSwitchesBegin[] = "flag-switches-begin"; -const char kFlagSwitchesEnd[] = "flag-switches-end"; - // Forces application mode. This hides certain system UI elements and forces // the app to be installed if it hasn't been already. const char kForceAppMode[] = "force-app-mode";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index f38e0dd..ce53949e 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -164,8 +164,6 @@ extern const char kExtensionsNotWebstore[]; extern const char kExtensionsUpdateFrequency[]; extern const char kFastStart[]; -extern const char kFlagSwitchesBegin[]; -extern const char kFlagSwitchesEnd[]; extern const char kForceAppMode[]; extern const char kForceFieldTrialParams[]; extern const char kForceFirstRun[];
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc index 06e262f..ad3fb13 100644 --- a/chrome/common/crash_keys.cc +++ b/chrome/common/crash_keys.cc
@@ -13,6 +13,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/common/chrome_switches.h" +#include "components/flags_ui/flags_ui_switches.h" #include "content/public/common/content_switches.h" #include "ipc/ipc_switches.h"
diff --git a/chrome/common/extensions/api/automation.idl b/chrome/common/extensions/api/automation.idl index f9037c5..c6f02b9 100644 --- a/chrome/common/extensions/api/automation.idl +++ b/chrome/common/extensions/api/automation.idl
@@ -334,9 +334,16 @@ // The $(ref:automation.StateType)s describing this node. object state; - // The rendered location (as a bounding box) of this node within the frame. + // The rendered location (as a bounding box) of this node in global + // screen coordinates. automation.Rect location; + // Computes the bounding box of a subrange of this node in global screen + // coordinates. Returns the same as |location| if range information + // is not available. The start and end indices are zero-based offsets + // into the node's "name" string attribute. + static automation.Rect boundsForRange(long startIndex, long endIndex); + // The purpose of the node, other than the role, if any. DOMString description;
diff --git a/chrome/common/localized_error.cc b/chrome/common/localized_error.cc index 30fed8b..f6d2fa70 100644 --- a/chrome/common/localized_error.cc +++ b/chrome/common/localized_error.cc
@@ -38,6 +38,7 @@ #endif using blink::WebURLError; +using error_page::OfflinePageStatus; // Some error pages have no details. const unsigned int kErrorPagesNoDetails = 0; @@ -554,7 +555,7 @@ bool is_post, bool stale_copy_in_cache, bool can_show_network_diagnostics_dialog, - bool has_offline_pages, + OfflinePageStatus offline_page_status, const std::string& locale, const std::string& accept_languages, scoped_ptr<error_page::ErrorPageParams> params, @@ -768,17 +769,29 @@ } #if defined(OS_ANDROID) - if (has_offline_pages) { - base::DictionaryValue* show_saved_pages_button = new base::DictionaryValue; - show_saved_pages_button->SetString( - "msg", - l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_PAGES)); - show_saved_pages_button->SetString( - "title", - l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_SHOW_SAVED_PAGES)); - error_strings->Set("showSavedPagesButton", show_saved_pages_button); + // Offline button will not be provided when we want to show something in the + // cache. + if (!show_saved_copy_visible) { + if (offline_page_status == OfflinePageStatus::HAS_OFFLINE_PAGE) { + base::DictionaryValue* show_offline_copy_button = + new base::DictionaryValue; + base::string16 button_text = + l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_SHOW_OFFLINE_COPY); + show_offline_copy_button->SetString("msg", button_text); + show_offline_copy_button->SetString("title", button_text); + error_strings->Set("showOfflineCopyButton", show_offline_copy_button); + } else if (offline_page_status == + OfflinePageStatus::HAS_OTHER_OFFLINE_PAGES) { + base::DictionaryValue* show_offline_pages_button = + new base::DictionaryValue; + base::string16 button_text = + l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_SHOW_OFFLINE_PAGES); + show_offline_pages_button->SetString("msg", button_text); + show_offline_pages_button->SetString("title", button_text); + error_strings->Set("showOfflinePagesButton", show_offline_pages_button); + } } -#endif +#endif // defined(OS_ANDROID) #if defined(OS_CHROMEOS) // ChromeOS has its own diagnostics extension, which doesn't rely on a
diff --git a/chrome/common/localized_error.h b/chrome/common/localized_error.h index 3237481..ed7ceb5 100644 --- a/chrome/common/localized_error.h +++ b/chrome/common/localized_error.h
@@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" +#include "components/error_page/common/offline_page_types.h" #include "url/gurl.h" namespace base { @@ -34,7 +35,7 @@ bool is_post, bool stale_copy_in_cache, bool can_show_network_diagnostics_dialog, - bool has_offline_pages, + error_page::OfflinePageStatus offline_page_status, const std::string& locale, const std::string& accept_languages, scoped_ptr<error_page::ErrorPageParams> params,
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index e096a93..95d7bf7 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h
@@ -15,6 +15,7 @@ #include "chrome/common/ntp_logging_events.h" #include "chrome/common/search_provider.h" #include "chrome/common/web_application_info.h" +#include "components/error_page/common/offline_page_types.h" #include "components/omnibox/common/omnibox_focus_state.h" #include "content/public/common/common_param_traits.h" #include "content/public/common/top_controls_state.h" @@ -75,6 +76,9 @@ blink::WebConsoleMessage::LevelLast) IPC_ENUM_TRAITS_MAX_VALUE(content::TopControlsState, content::TOP_CONTROLS_STATE_LAST) +IPC_ENUM_TRAITS_MAX_VALUE( + error_page::OfflinePageStatus, + error_page::OfflinePageStatus::OFFLINE_PAGE_STATUS_LAST) // Output parameters for ChromeViewHostMsg_GetPluginInfo message. IPC_STRUCT_BEGIN(ChromeViewHostMsg_GetPluginInfo_Output) @@ -323,11 +327,11 @@ bool /* can_show_network_diagnostics_dialog */) #if defined(OS_ANDROID) -// Tells the renderer whether or not an offline page exists. This is used to -// decide if "show saved pages" button will be provided on certain error page. -IPC_MESSAGE_ROUTED1(ChromeViewMsg_SetHasOfflinePages, - bool /* has_offline_pages */) -#endif +// Tells the renderer about the status of the offline pages. This is used to +// decide if offline related button will be provided on certain error page. +IPC_MESSAGE_ROUTED1(ChromeViewMsg_SetOfflinePageInfo, + error_page::OfflinePageStatus /* offline_page_status */) +#endif // defined(OS_ANDROID) // Provides the information needed by the renderer process to contact a // navigation correction service. Handled by the NetErrorHelper. @@ -345,7 +349,11 @@ // Message sent from the renderer to the browser to show the UI for offline // pages. IPC_MESSAGE_ROUTED0(ChromeViewHostMsg_ShowOfflinePages) -#endif + +// Message sent from the renderer to the browser to load the offline copy of +// the page that fails to load due to no network connectivity. +IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_LoadOfflineCopy, GURL /* url */) +#endif // defined(OS_ANDROID) //----------------------------------------------------------------------------- // Misc messages
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 45b3c13..afb1e67 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -380,9 +380,6 @@ "http://support.google.com/installer/?product=" "{8A69D345-D564-463c-AFF1-A69D9E530F96}&error="; -const char kPasswordManagerAccountDashboardURL[] = - "https://passwords.google.com/settings/passwords"; - const char kSmartLockHelpPage[] = "https://support.google.com/accounts/answer/6197437";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index d865f871..184c1de0 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -347,7 +347,6 @@ extern const char kPasswordManagerLearnMoreURL[]; extern const char kUpgradeHelpCenterBaseURL[]; -extern const char kPasswordManagerAccountDashboardURL[]; extern const char kSmartLockHelpPage[]; // "Learn more" URL for the Settings API, NTP bubble and other settings bubbles
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn index 0829120..d04febf 100644 --- a/chrome/installer/mini_installer/BUILD.gn +++ b/chrome/installer/mini_installer/BUILD.gn
@@ -162,6 +162,10 @@ #"../chrome.gyp:chrome_nacl_win64", TODO(GYP) bug 512869. ] + + if (enable_nacl) { + deps += [ "//ppapi/native_client:irt" ] + } } # TODO(GYP) bug 521052: This target needs to be checked to make sure its the
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 4ab9a7e8..a7519cc 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -30,7 +30,6 @@ defines = [] deps = [ - "//base/allocator", "//chrome:resources", "//chrome:strings", "//chrome/common",
diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc index 22c1852..543032b 100644 --- a/chrome/renderer/chrome_render_process_observer.cc +++ b/chrome/renderer/chrome_render_process_observer.cc
@@ -7,7 +7,6 @@ #include <limits> #include <vector> -#include "base/allocator/allocator_extension.h" #include "base/bind.h" #include "base/command_line.h" #include "base/files/file_util.h"
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc index 0ecab81..e68edce 100644 --- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc +++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -63,6 +63,81 @@ v8::String::kNormalString, str.length()); } +v8::Local<v8::Object> RectToV8Object(v8::Isolate* isolate, + const gfx::Rect& rect) { + v8::Local<v8::Object> result(v8::Object::New(isolate)); + result->Set(CreateV8String(isolate, "left"), + v8::Integer::New(isolate, rect.x())); + result->Set(CreateV8String(isolate, "top"), + v8::Integer::New(isolate, rect.y())); + result->Set(CreateV8String(isolate, "width"), + v8::Integer::New(isolate, rect.width())); + result->Set(CreateV8String(isolate, "height"), + v8::Integer::New(isolate, rect.height())); + return result; +} + +// Compute the bounding box of a node, fixing nodes with empty bounds by +// unioning the bounds of their children. +static gfx::Rect ComputeLocalNodeBounds(TreeCache* cache, ui::AXNode* node) { + gfx::Rect bounds = node->data().location; + if (bounds.width() > 0 && bounds.height() > 0) + return bounds; + + // Compute the bounds of each child. + for (size_t i = 0; i < node->children().size(); i++) { + ui::AXNode* child = node->children()[i]; + gfx::Rect child_bounds = ComputeLocalNodeBounds(cache, child); + + // Ignore children that don't have valid bounds themselves. + if (child_bounds.width() == 0 || child_bounds.height() == 0) + continue; + + // For the first valid child, just set the bounds to that child's bounds. + if (bounds.width() == 0 || bounds.height() == 0) { + bounds = child_bounds; + continue; + } + + // Union each additional child's bounds. + bounds.Union(child_bounds); + } + + return bounds; +} + +// Compute the bounding box of a node in global coordinates, walking up the +// parent hierarchy to offset by frame offsets and scroll offsets. +static gfx::Rect ComputeGlobalNodeBounds(TreeCache* cache, ui::AXNode* node) { + gfx::Rect bounds = ComputeLocalNodeBounds(cache, node); + ui::AXNode* parent = node->parent(); + bool need_to_offset_web_area = node->data().role == ui::AX_ROLE_WEB_AREA || + node->data().role == ui::AX_ROLE_ROOT_WEB_AREA; + while (parent) { + if (bounds.IsEmpty()) { + bounds = parent->data().location; + } else if (need_to_offset_web_area && parent->data().location.width() > 0 && + parent->data().location.height() > 0) { + bounds.Offset(parent->data().location.x(), parent->data().location.y()); + need_to_offset_web_area = false; + } + + if (parent->data().role == ui::AX_ROLE_WEB_AREA || + parent->data().role == ui::AX_ROLE_ROOT_WEB_AREA) { + int sx = 0; + int sy = 0; + if (parent->data().GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && + parent->data().GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { + bounds.Offset(-sx, -sy); + } + need_to_offset_web_area = true; + } + parent = parent->parent(); + } + + return bounds; +} + // // Helper class that helps implement bindings for a JavaScript function // that takes a single input argument consisting of a Tree ID. Looks up @@ -202,6 +277,59 @@ NodeIDPlusAttributeFunction function_; }; +// +// Helper class that helps implement bindings for a JavaScript function +// that takes four input arguments: a tree ID, node ID, and integer start +// and end indices. Looks up the TreeCache and the AXNode and passes them +// to the function passed to the constructor. +// + +typedef void (*NodeIDPlusRangeFunction)(v8::Isolate* isolate, + v8::ReturnValue<v8::Value> result, + TreeCache* cache, + ui::AXNode* node, + int start, + int end); + +class NodeIDPlusRangeWrapper + : public base::RefCountedThreadSafe<NodeIDPlusRangeWrapper> { + public: + NodeIDPlusRangeWrapper(AutomationInternalCustomBindings* automation_bindings, + NodeIDPlusRangeFunction function) + : automation_bindings_(automation_bindings), function_(function) {} + + void Run(const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::Isolate* isolate = automation_bindings_->GetIsolate(); + if (args.Length() < 4 || !args[0]->IsNumber() || !args[1]->IsNumber() || + !args[2]->IsNumber() || !args[3]->IsNumber()) { + ThrowInvalidArgumentsException(automation_bindings_); + } + + int tree_id = args[0]->Int32Value(); + int node_id = args[1]->Int32Value(); + int start = args[2]->Int32Value(); + int end = args[3]->Int32Value(); + + TreeCache* cache = automation_bindings_->GetTreeCacheFromTreeID(tree_id); + if (!cache) + return; + + ui::AXNode* node = cache->tree.GetFromId(node_id); + if (!node) + return; + + function_(isolate, args.GetReturnValue(), cache, node, start, end); + } + + private: + virtual ~NodeIDPlusRangeWrapper() {} + + friend class base::RefCountedThreadSafe<NodeIDPlusRangeWrapper>; + + AutomationInternalCustomBindings* automation_bindings_; + NodeIDPlusRangeFunction function_; +}; + } // namespace TreeCache::TreeCache() {} @@ -378,18 +506,52 @@ RouteNodeIDFunction( "GetLocation", [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, TreeCache* cache, ui::AXNode* node) { - v8::Local<v8::Object> location_obj(v8::Object::New(isolate)); - gfx::Rect location = node->data().location; + gfx::Rect location = ComputeGlobalNodeBounds(cache, node); location.Offset(cache->location_offset); - location_obj->Set(CreateV8String(isolate, "left"), - v8::Integer::New(isolate, location.x())); - location_obj->Set(CreateV8String(isolate, "top"), - v8::Integer::New(isolate, location.y())); - location_obj->Set(CreateV8String(isolate, "width"), - v8::Integer::New(isolate, location.width())); - location_obj->Set(CreateV8String(isolate, "height"), - v8::Integer::New(isolate, location.height())); - result.Set(location_obj); + result.Set(RectToV8Object(isolate, location)); + }); + + // Bindings that take a Tree ID and Node ID and string attribute name + // and return a property of the node. + + RouteNodeIDPlusRangeFunction( + "GetBoundsForRange", + [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, + TreeCache* cache, ui::AXNode* node, int start, int end) { + gfx::Rect location = ComputeGlobalNodeBounds(cache, node); + location.Offset(cache->location_offset); + if (node->data().role == ui::AX_ROLE_INLINE_TEXT_BOX) { + std::string name = node->data().GetStringAttribute(ui::AX_ATTR_NAME); + std::vector<int> character_offsets = + node->data().GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS); + int len = + static_cast<int>(std::min(name.size(), character_offsets.size())); + if (start >= 0 && start <= end && end <= len) { + int start_offset = start > 0 ? character_offsets[start - 1] : 0; + int end_offset = end > 0 ? character_offsets[end - 1] : 0; + + switch (node->data().GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION)) { + case ui::AX_TEXT_DIRECTION_LTR: + default: + location.set_x(location.x() + start_offset); + location.set_width(end_offset - start_offset); + break; + case ui::AX_TEXT_DIRECTION_RTL: + location.set_x(location.x() + location.width() - end_offset); + location.set_width(end_offset - start_offset); + break; + case ui::AX_TEXT_DIRECTION_TTB: + location.set_y(location.y() + start_offset); + location.set_height(end_offset - start_offset); + break; + case ui::AX_TEXT_DIRECTION_BTT: + location.set_y(location.y() + location.height() - end_offset); + location.set_height(end_offset - start_offset); + break; + } + } + } + result.Set(RectToV8Object(isolate, location)); }); // Bindings that take a Tree ID and Node ID and string attribute name @@ -592,6 +754,14 @@ RouteFunction(name, base::Bind(&NodeIDPlusAttributeWrapper::Run, wrapper)); } +void AutomationInternalCustomBindings::RouteNodeIDPlusRangeFunction( + const std::string& name, + NodeIDPlusRangeFunction callback) { + scoped_refptr<NodeIDPlusRangeWrapper> wrapper = + new NodeIDPlusRangeWrapper(this, callback); + RouteFunction(name, base::Bind(&NodeIDPlusRangeWrapper::Run, wrapper)); +} + void AutomationInternalCustomBindings::GetChildIDAtIndex( const v8::FunctionCallbackInfo<v8::Value>& args) { if (args.Length() < 3 || !args[2]->IsNumber()) {
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.h b/chrome/renderer/extensions/automation_internal_custom_bindings.h index 5be7c9d..94e659db 100644 --- a/chrome/renderer/extensions/automation_internal_custom_bindings.h +++ b/chrome/renderer/extensions/automation_internal_custom_bindings.h
@@ -91,6 +91,14 @@ v8::ReturnValue<v8::Value> result, ui::AXNode* node, const std::string& attribute_name)); + void RouteNodeIDPlusRangeFunction( + const std::string& name, + void (*callback)(v8::Isolate* isolate, + v8::ReturnValue<v8::Value> result, + TreeCache* cache, + ui::AXNode* node, + int start, + int end)); // // Access the cached accessibility trees and properties of their nodes.
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc index 492c9d3..d739cdc 100644 --- a/chrome/renderer/net/net_error_helper.cc +++ b/chrome/renderer/net/net_error_helper.cc
@@ -50,6 +50,7 @@ using error_page::DnsProbeStatusToString; using error_page::ErrorPageParams; using error_page::NetErrorHelperCore; +using error_page::OfflinePageStatus; namespace { @@ -146,7 +147,7 @@ IPC_MESSAGE_HANDLER(ChromeViewMsg_SetNavigationCorrectionInfo, OnSetNavigationCorrectionInfo); #if defined(OS_ANDROID) - IPC_MESSAGE_HANDLER(ChromeViewMsg_SetHasOfflinePages, OnSetHasOfflinePages) + IPC_MESSAGE_HANDLER(ChromeViewMsg_SetOfflinePageInfo, OnSetOfflinePageInfo) #endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -174,12 +175,13 @@ const blink::WebURLError& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - bool has_offline_pages, + OfflinePageStatus offline_page_status, scoped_ptr<ErrorPageParams> params, bool* reload_button_shown, bool* show_saved_copy_button_shown, bool* show_cached_copy_button_shown, - bool* show_saved_pages_button_shown, + bool* show_offline_pages_button_shown, + bool* show_offline_copy_button_shown, std::string* error_html) const { error_html->clear(); @@ -190,22 +192,27 @@ NOTREACHED() << "unable to load template."; } else { base::DictionaryValue error_strings; - LocalizedError::GetStrings(error.reason, error.domain.utf8(), - error.unreachableURL, is_failed_post, - error.staleCopyInCache, - can_show_network_diagnostics_dialog, - has_offline_pages, - RenderThread::Get()->GetLocale(), - render_frame()->GetRenderView()-> - GetAcceptLanguages(), - params.Pass(), &error_strings); + LocalizedError::GetStrings( + error.reason, + error.domain.utf8(), + error.unreachableURL, + is_failed_post, + error.staleCopyInCache, + can_show_network_diagnostics_dialog, + offline_page_status, + RenderThread::Get()->GetLocale(), + render_frame()->GetRenderView()->GetAcceptLanguages(), + params.Pass(), + &error_strings); *reload_button_shown = error_strings.Get("reloadButton", nullptr); *show_saved_copy_button_shown = error_strings.Get("showSavedCopyButton", nullptr); *show_cached_copy_button_shown = error_strings.Get("cacheButton", nullptr); - *show_saved_pages_button_shown = - error_strings.Get("showSavedPagesButton", nullptr); + *show_offline_pages_button_shown = + error_strings.Get("showOfflinePagesButton", nullptr); + *show_offline_copy_button_shown = + error_strings.Get("showOfflineCopyButton", nullptr); // "t" is the id of the template's root node. *error_html = webui::GetTemplatesHtml(template_html, &error_strings, "t"); } @@ -225,20 +232,20 @@ void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - bool has_offline_pages) { + OfflinePageStatus offline_page_status) { base::DictionaryValue error_strings; - LocalizedError::GetStrings(error.reason, - error.domain.utf8(), - error.unreachableURL, - is_failed_post, - error.staleCopyInCache, - can_show_network_diagnostics_dialog, - has_offline_pages, - RenderThread::Get()->GetLocale(), - render_frame()->GetRenderView()-> - GetAcceptLanguages(), - scoped_ptr<ErrorPageParams>(), - &error_strings); + LocalizedError::GetStrings( + error.reason, + error.domain.utf8(), + error.unreachableURL, + is_failed_post, + error.staleCopyInCache, + can_show_network_diagnostics_dialog, + offline_page_status, + RenderThread::Get()->GetLocale(), + render_frame()->GetRenderView()->GetAcceptLanguages(), + scoped_ptr<ErrorPageParams>(), + &error_strings); std::string json; JSONWriter::Write(error_strings, &json); @@ -324,7 +331,14 @@ #if defined(OS_ANDROID) render_frame()->Send(new ChromeViewHostMsg_ShowOfflinePages( render_frame()->GetRoutingID())); -#endif +#endif // defined(OS_ANDROID) +} + +void NetErrorHelper::LoadOfflineCopy(const GURL& page_url) { +#if defined(OS_ANDROID) + render_frame()->Send(new ChromeViewHostMsg_LoadOfflineCopy( + render_frame()->GetRoutingID(), page_url)); +#endif // defined(OS_ANDROID) } void NetErrorHelper::OnNetErrorInfo(int status_num) { @@ -372,7 +386,8 @@ } #if defined(OS_ANDROID) -void NetErrorHelper::OnSetHasOfflinePages(bool has_offline_pages) { - core_->OnSetHasOfflinePages(has_offline_pages); +void NetErrorHelper::OnSetOfflinePageInfo( + OfflinePageStatus offline_page_status) { + core_->OnSetOfflinePageInfo(offline_page_status); } -#endif +#endif // defined(OS_ANDROID)
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h index 935cd5df..333fb66e 100644 --- a/chrome/renderer/net/net_error_helper.h +++ b/chrome/renderer/net/net_error_helper.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/renderer/net/net_error_page_controller.h" #include "components/error_page/common/net_error_info.h" +#include "components/error_page/common/offline_page_types.h" #include "components/error_page/renderer/net_error_helper_core.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" @@ -83,19 +84,21 @@ const blink::WebURLError& error, bool is_failed_post, bool can_use_local_diagnostics_service, - bool has_offline_pages, + error_page::OfflinePageStatus offline_page_status, scoped_ptr<error_page::ErrorPageParams> params, bool* reload_button_shown, bool* show_saved_copy_button_shown, bool* show_cached_copy_button_shown, - bool* show_saved_pages_button_shown, + bool* show_offline_pages_button_shown, + bool* show_offline_copy_button_shown, std::string* html) const override; void LoadErrorPage(const std::string& html, const GURL& failed_url) override; void EnablePageHelperFunctions() override; - void UpdateErrorPage(const blink::WebURLError& error, - bool is_failed_post, - bool can_use_local_diagnostics_service, - bool has_offline_pages) override; + void UpdateErrorPage( + const blink::WebURLError& error, + bool is_failed_post, + bool can_use_local_diagnostics_service, + error_page::OfflinePageStatus offline_page_status) override; void FetchNavigationCorrections( const GURL& navigation_correction_url, const std::string& navigation_correction_request_body) override; @@ -106,6 +109,7 @@ void LoadPageFromCache(const GURL& page_url) override; void DiagnoseError(const GURL& page_url) override; void ShowOfflinePages() override; + void LoadOfflineCopy(const GURL& page_url) override; void OnNetErrorInfo(int status); void OnSetCanShowNetworkDiagnosticsDialog( @@ -121,8 +125,11 @@ void OnTrackingRequestComplete(const blink::WebURLResponse& response, const std::string& data); + #if defined(OS_ANDROID) - void OnSetHasOfflinePages(bool has_offline_pages); + // Called to set the status of the offline pages that will be used to decide + // if offline related button will be provided in the error page. + void OnSetOfflinePageInfo(error_page::OfflinePageStatus offline_page_status); #endif scoped_ptr<content::ResourceFetcher> correction_fetcher_;
diff --git a/chrome/renderer/net/net_error_page_controller.cc b/chrome/renderer/net/net_error_page_controller.cc index f9a2ed3..be4aae4a 100644 --- a/chrome/renderer/net/net_error_page_controller.cc +++ b/chrome/renderer/net/net_error_page_controller.cc
@@ -43,8 +43,12 @@ return ButtonClick(error_page::NetErrorHelperCore::SHOW_SAVED_COPY_BUTTON); } -bool NetErrorPageController::ShowSavedPagesButtonClick() { - return ButtonClick(error_page::NetErrorHelperCore::SHOW_SAVED_PAGES_BUTTON); +bool NetErrorPageController::ShowOfflinePagesButtonClick() { + return ButtonClick(error_page::NetErrorHelperCore::SHOW_OFFLINE_PAGES_BUTTON); +} + +bool NetErrorPageController::ShowOfflineCopyButtonClick() { + return ButtonClick(error_page::NetErrorHelperCore::SHOW_OFFLINE_COPY_BUTTON); } bool NetErrorPageController::ReloadButtonClick() { @@ -96,18 +100,18 @@ isolate) .SetMethod("showSavedCopyButtonClick", &NetErrorPageController::ShowSavedCopyButtonClick) - .SetMethod("showSavedPagesButtonClick", - &NetErrorPageController::ShowSavedPagesButtonClick) + .SetMethod("showOfflinePagesButtonClick", + &NetErrorPageController::ShowOfflinePagesButtonClick) + .SetMethod("showOfflineCopyButtonClick", + &NetErrorPageController::ShowOfflineCopyButtonClick) .SetMethod("reloadButtonClick", &NetErrorPageController::ReloadButtonClick) .SetMethod("detailsButtonClick", &NetErrorPageController::DetailsButtonClick) .SetMethod("diagnoseErrorsButtonClick", &NetErrorPageController::DiagnoseErrorsButtonClick) - .SetMethod("trackClick", - &NetErrorPageController::TrackClick) - .SetMethod("trackEasterEgg", - &NetErrorPageController::TrackEasterEgg) + .SetMethod("trackClick", &NetErrorPageController::TrackClick) + .SetMethod("trackEasterEgg", &NetErrorPageController::TrackEasterEgg) .SetMethod("trackCachedCopyButtonClick", &NetErrorPageController::TrackCachedCopyButtonClick); }
diff --git a/chrome/renderer/net/net_error_page_controller.h b/chrome/renderer/net/net_error_page_controller.h index 95216cbf..59dceb2c 100644 --- a/chrome/renderer/net/net_error_page_controller.h +++ b/chrome/renderer/net/net_error_page_controller.h
@@ -54,8 +54,11 @@ // Execute a "Show saved copy" button click. bool ShowSavedCopyButtonClick(); - // Execute a "Show saved pages" button click. - bool ShowSavedPagesButtonClick(); + // Execute a button click to show the list of all offline pages. + bool ShowOfflinePagesButtonClick(); + + // Execute a button click to show the offline copy of this page. + bool ShowOfflineCopyButtonClick(); // Execute a "Reload" button click. bool ReloadButtonClick();
diff --git a/chrome/renderer/resources/extensions/automation/automation_node.js b/chrome/renderer/resources/extensions/automation/automation_node.js index d6eac92..4e3a2d46 100644 --- a/chrome/renderer/resources/extensions/automation/automation_node.js +++ b/chrome/renderer/resources/extensions/automation/automation_node.js
@@ -124,6 +124,17 @@ /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. + * @param {number} startIndex The start index of the range. + * @param {number} endIndex The end index of the range. + * @return {?automation.Rect} The bounding box of the subrange of this node, + * or the location if there are no subranges, or undefined if + * the tree or node wasn't found. + */ +var GetBoundsForRange = requireNative('automationInternal').GetBoundsForRange; + +/** + * @param {number} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. * @param {string} attr The name of a string attribute. * @return {?string} The value of this attribute, or undefined if the tree, * node, or attribute wasn't found. @@ -222,6 +233,10 @@ return GetLocation(this.treeID, this.id); }, + boundsForRange: function(startIndex, endIndex) { + return GetBoundsForRange(this.treeID, this.id, startIndex, endIndex); + }, + get indexInParent() { return GetIndexInParent(this.treeID, this.id); }, @@ -935,7 +950,8 @@ 'addEventListener', 'removeEventListener', 'domQuerySelector', - 'toString' ], + 'toString', + 'boundsForRange'], readonly: publicAttributes.concat( ['parent', 'firstChild',
diff --git a/chrome/renderer/resources/neterror.css b/chrome/renderer/resources/neterror.css index 29c8dc2d..d364ffd 100644 --- a/chrome/renderer/resources/neterror.css +++ b/chrome/renderer/resources/neterror.css
@@ -72,6 +72,11 @@ margin: 20px; } +.gray-button { + background: #d9d9d9; + color: #696969; +} + #help-box-inner { background-color: #f9f9f9; border-top: 1px solid #EEE; @@ -452,4 +457,4 @@ button { width: auto; } -} \ No newline at end of file +}
diff --git a/chrome/renderer/resources/neterror.html b/chrome/renderer/resources/neterror.html index 9e8973a4..f1fba59 100644 --- a/chrome/renderer/resources/neterror.html +++ b/chrome/renderer/resources/neterror.html
@@ -37,10 +37,16 @@ jsselect="showSavedCopyButton" jscontent="msg" jsvalues="title:title; .primary:primary"> </button> - <button id="show-saved-pages-button" + <button id="show-offline-pages-button" + class="gray-button text-button" + onclick="showOfflinePagesButtonClick()" + jsselect="showOfflinePagesButton" + jscontent="msg" jsvalues="title:title"> + </button> + <button id="show-offline-copy-button" class="blue-button text-button" - onclick="showSavedPagesButtonClick()" - jsselect="showSavedPagesButton" + onclick="showOfflineCopyButtonClick()" + jsselect="showOfflineCopyButton" jscontent="msg" jsvalues="title:title; .primary:primary"> </button> </div>
diff --git a/chrome/renderer/resources/neterror.js b/chrome/renderer/resources/neterror.js index 5bab31d..773d82fb 100644 --- a/chrome/renderer/resources/neterror.js +++ b/chrome/renderer/resources/neterror.js
@@ -114,9 +114,15 @@ } } -function showSavedPagesButtonClick() { +function showOfflinePagesButtonClick() { if (window.errorPageController) { - errorPageController.showSavedPagesButtonClick(); + errorPageController.showOfflinePagesButtonClick(); + } +} + +function showOfflineCopyButtonClick() { + if (window.errorPageController) { + errorPageController.showOfflineCopyButtonClick(); } } @@ -156,27 +162,29 @@ var reloadButton = document.getElementById('reload-button'); var detailsButton = document.getElementById('details-button'); var showSavedCopyButton = document.getElementById('show-saved-copy-button'); - var showSavedPagesButton = document.getElementById('show-saved-pages-button'); + var showOfflinePagesButton = + document.getElementById('show-offline-pages-button'); + var showOfflineCopyButton = + document.getElementById('show-offline-copy-button'); - // "Show save pages" button will only be provided in ERR_INTERNET_DISCONNECTED - // page where "Reload" button will not be provided. var reloadButtonVisible = loadTimeData.valueExists('reloadButton') && loadTimeData.getValue('reloadButton').msg; var showSavedCopyButtonVisible = loadTimeData.valueExists('showSavedCopyButton') && loadTimeData.getValue('showSavedCopyButton').msg; - var showSavedPagesButtonVisible = - loadTimeData.valueExists('showSavedPagesButton') && - loadTimeData.getValue('showSavedPagesButton').msg; + var showOfflinePagesButtonVisible = + loadTimeData.valueExists('showOfflinePagesButton') && + loadTimeData.getValue('showOfflinePagesButton').msg; + var showOfflineCopyButtonVisible = + loadTimeData.valueExists('showOfflineCopyButton') && + loadTimeData.getValue('showOfflineCopyButton').msg; var primaryButton, secondaryButton; if (showSavedCopyButton.primary) { primaryButton = showSavedCopyButton; - secondaryButton = - showSavedPagesButtonVisible ? showSavedPagesButton : reloadButton; + secondaryButton = reloadButton; } else { - primaryButton = - showSavedPagesButtonVisible ? showSavedPagesButton : reloadButton; + primaryButton = reloadButton; secondaryButton = showSavedCopyButton; } @@ -196,7 +204,8 @@ if (reloadButton.style.display == 'none' && showSavedCopyButton.style.display == 'none' && - showSavedPagesButton.style.display == 'none') { + showOfflinePagesButton.style.display == 'none' && + showOfflineCopyButton.style.display == 'none') { detailsButton.classList.add('singular'); } @@ -210,11 +219,12 @@ // Show control buttons. if (reloadButtonVisible || showSavedCopyButtonVisible || - showSavedPagesButtonVisible) { + showOfflinePagesButtonVisible || showOfflineCopyButton) { controlButtonDiv.hidden = false; // Set the secondary button state in the cases of two call to actions. - if ((reloadButtonVisible || showSavedPagesButtonVisible) && + if ((reloadButtonVisible || showOfflinePagesButtonVisible || + showOfflineCopyButton) && showSavedCopyButtonVisible) { secondaryButton.classList.add('secondary-button'); }
diff --git a/chrome/telemetry_unittests.isolate b/chrome/telemetry_unittests.isolate index f91ea698..fb8c401 100644 --- a/chrome/telemetry_unittests.isolate +++ b/chrome/telemetry_unittests.isolate
@@ -15,12 +15,31 @@ '../testing/scripts/common.py', '../testing/scripts/run_telemetry_as_googletest.py', ], + } + }], + ['OS=="mac"', { + 'variables': { 'command': [ '../testing/scripts/run_telemetry_as_googletest.py', '../tools/telemetry/run_tests', '-v', '--chrome-root', - '..' + '..', + ], + }, + }], + ['OS=="win"', { + 'variables': { + 'command': [ + '../testing/scripts/run_telemetry_as_googletest.py', + '../tools/telemetry/run_tests', + '-v', + '--chrome-root', + '..', + # crbug.com/559154 + # TODO(nednguyen): Remove --jobs=1 once the bug is fixed to speed up + # the test run. + '--job=1', ], }, }],
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 88d7b73..38f4bfb 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2103,12 +2103,14 @@ ] deps = [ ":test_support", + "//base/allocator", "//base/test:run_all_unittests", "//base/test:test_support", "//breakpad:client", "//chrome/browser", "//chrome/child", "//components/crash/core/common", + "//components/flags_ui:switches", ] if (cld_version == 2) { # Use whatever CLD2 data access mode that the @@ -2130,6 +2132,7 @@ ":test_support_ui", "//base", "//base:i18n", + "//base/allocator", "//base/test:test_support", "//chrome/browser", "//chrome/renderer",
diff --git a/chrome/test/data/extensions/api_test/automation/sites/bounds_for_range.html b/chrome/test/data/extensions/api_test/automation/sites/bounds_for_range.html new file mode 100644 index 0000000..7341973 --- /dev/null +++ b/chrome/test/data/extensions/api_test/automation/sites/bounds_for_range.html
@@ -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. +--> +<html> +<head> +<title>Automation Tests - Bounds for Range</title> +<meta charset="utf-8"> +<style> + li { + font-size: 16pt; + margin: 20px; + } +</style> +</head> +<body> + <ul> + <li id="ltr">Hello world</li> + + <li id="rtl">שלום עולם</li> + + <li id="ttb" style="-webkit-writing-mode: vertical-lr">Hello world</li> + + <li id="btt" style="-webkit-writing-mode: vertical-rl">שלום עולם</li> + </ul> + +</body> +</html>
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/bounds_for_range.html b/chrome/test/data/extensions/api_test/automation/tests/tabs/bounds_for_range.html new file mode 100644 index 0000000..f1dc8a2 --- /dev/null +++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/bounds_for_range.html
@@ -0,0 +1,7 @@ +<!-- + * Copyright 2015 The Chromium 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="common.js"></script> +<script src="bounds_for_range.js"></script>
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/bounds_for_range.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/bounds_for_range.js new file mode 100644 index 0000000..73bfc35c --- /dev/null +++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/bounds_for_range.js
@@ -0,0 +1,86 @@ +// Copyright 2015 The Chromium 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 RoleType = chrome.automation.RoleType; + +var allTests = [ + function boundsForRange() { + function getNthListItemInlineTextBox(index) { + var list = rootNode.find({role: RoleType.list}); + var listItem = list.children[index]; + assertEq(RoleType.listItem, listItem.role); + var staticText = listItem.children[1]; + assertEq(RoleType.staticText, staticText.role); + var inlineTextBox = staticText.firstChild; + assertEq(RoleType.inlineTextBox, inlineTextBox.role); + return inlineTextBox; + } + + // Left-to-right. + var ltr = getNthListItemInlineTextBox(0); + var bounds = ltr.location; + var firstHalf = ltr.boundsForRange(0, 4); + var secondHalf = ltr.boundsForRange(4, ltr.name.length); + assertEq(bounds.top, firstHalf.top); + assertEq(bounds.left, firstHalf.left); + assertEq(bounds.height, firstHalf.height); + assertEq(bounds.top, secondHalf.top); + assertEq(bounds.height, secondHalf.height); + assertTrue(secondHalf.left > bounds.left); + assertTrue(firstHalf.width < bounds.width); + assertTrue(secondHalf.width < bounds.width); + assertTrue(Math.abs(bounds.width - firstHalf.width - secondHalf.width) < 3); + + // Right-to-left. + var rtl = getNthListItemInlineTextBox(1); + bounds = rtl.location; + firstHalf = rtl.boundsForRange(0, 4); + secondHalf = rtl.boundsForRange(4, rtl.name.length); + assertEq(bounds.top, secondHalf.top); + assertTrue(Math.abs(bounds.left - secondHalf.left) < 3); + assertEq(bounds.height, secondHalf.height); + assertEq(bounds.top, firstHalf.top); + assertEq(bounds.height, firstHalf.height); + assertTrue(firstHalf.left > bounds.left); + assertTrue(secondHalf.width < bounds.width); + assertTrue(firstHalf.width < bounds.width); + assertTrue(Math.abs(bounds.width - secondHalf.width - firstHalf.width) < 3); + + // Top-to-bottom. + var ttb = getNthListItemInlineTextBox(2); + var bounds = ttb.location; + var firstHalf = ttb.boundsForRange(0, 4); + var secondHalf = ttb.boundsForRange(4, ttb.name.length); + assertEq(bounds.left, firstHalf.left); + assertEq(bounds.top, firstHalf.top); + assertEq(bounds.width, firstHalf.width); + assertEq(bounds.left, secondHalf.left); + assertEq(bounds.width, secondHalf.width); + assertTrue(secondHalf.top > bounds.top); + assertTrue(firstHalf.height < bounds.height); + assertTrue(secondHalf.height < bounds.height); + assertTrue(Math.abs(bounds.height - firstHalf.height - secondHalf.height) + < 3); + + // Bottom-to-top. + var btt = getNthListItemInlineTextBox(3); + bounds = btt.location; + firstHalf = btt.boundsForRange(0, 4); + secondHalf = btt.boundsForRange(4, btt.name.length); + assertEq(bounds.left, secondHalf.left); + assertTrue(Math.abs(bounds.top - secondHalf.top) < 3); + assertEq(bounds.width, secondHalf.width); + assertEq(bounds.left, firstHalf.left); + assertEq(bounds.width, firstHalf.width); + assertTrue(firstHalf.top > bounds.top); + assertTrue(secondHalf.height < bounds.height); + assertTrue(firstHalf.height < bounds.height); + assertTrue(Math.abs(bounds.height - secondHalf.height - firstHalf.height) + < 3); + chrome.test.succeed(); + + } +]; + +setUpAndRunTests(allTests, 'bounds_for_range.html');
diff --git a/chrome/test/data/extensions/api_test/socket/api/background.js b/chrome/test/data/extensions/api_test/socket/api/background.js index 35ecffa4..ff4864a 100644 --- a/chrome/test/data/extensions/api_test/socket/api/background.js +++ b/chrome/test/data/extensions/api_test/socket/api/background.js
@@ -206,6 +206,7 @@ setTimeout(function() { socket.getInfo(acceptedSocketId, function(info) { chrome.test.assertFalse(info.connected); + socket.destroy(socketId); chrome.test.succeed(); }); }, 500); @@ -247,6 +248,46 @@ socket.create('tcp', {}, onServerSocketCreate); }; +// Tests creation of a TCP listening socket on a port that is already in use. +var testSocketListenInUse = function() { + var tmpSocketId; + + function onAccept(result) { + chrome.test.assertNoLastError(); + chrome.test.assertEq(-2, result.resultCode); + socket.destroy(socketId); + socket.destroy(tmpSocketId); + chrome.test.succeed(); + } + + function onSecondSocketListen(result) { + chrome.test.assertLastError("Could not listen on the specified port."); + chrome.test.assertEq(-147, result); + // Calling accept on this socket should fail since it isn't listening. + socket.accept(tmpSocketId, onAccept); + } + + function onSecondSocketCreate(socketInfo) { + chrome.test.assertNoLastError(); + tmpSocketId = socketInfo.socketId; + socket.listen(tmpSocketId, address, port, onSecondSocketListen); + } + + function onFirstSocketListen(result) { + chrome.test.assertNoLastError(); + chrome.test.assertEq(0, result); + socket.create('tcp', {}, onSecondSocketCreate); + } + + function onFirstSocketCreate(socketInfo) { + chrome.test.assertNoLastError(); + socketId = socketInfo.socketId; + socket.listen(socketId, address, port, onFirstSocketListen); + } + + socket.create('tcp', {}, onFirstSocketCreate); +}; + var testPendingCallback = function() { dataRead = ""; succeeded = false; @@ -374,7 +415,10 @@ console.log("Running tests, protocol " + protocol + ", echo server " + address + ":" + port); if (test_type == 'tcp_server') { - chrome.test.runTests([ testSocketListening ]); + chrome.test.runTests([ + testSocketListening, + testSocketListenInUse + ]); } else if (test_type == 'multicast') { console.log("Running multicast tests"); chrome.test.runTests([ testMulticast ]);
diff --git a/chromecast/media/empty.cc b/chrome/test/data/extensions/api_test/webstore_inline_install/empty.html similarity index 100% rename from chromecast/media/empty.cc rename to chrome/test/data/extensions/api_test/webstore_inline_install/empty.html
diff --git a/chrome/test/data/webui/settings/dropdown_menu_tests.js b/chrome/test/data/webui/settings/dropdown_menu_tests.js index 5dbdbf9..f3531e5 100644 --- a/chrome/test/data/webui/settings/dropdown_menu_tests.js +++ b/chrome/test/data/webui/settings/dropdown_menu_tests.js
@@ -37,8 +37,10 @@ type: chrome.settingsPrivate.PrefType.NUMBER, value: 100, }; - dropdown.menuOptions = [[100, 'Option 100'], [200, 'Option 200'], - [300, 'Option 300'], [400, 'Option 400']]; + dropdown.menuOptions = [{value: 100, name: 'Option 100'}, + {value: 200, name: 'Option 200'}, + {value: 300, name: 'Option 300'}, + {value: 400, name: 'Option 400'}]; // IronSelectable uses a DOM observer, which uses a debouncer. Polymer.dom.flush(); @@ -62,7 +64,10 @@ value: 'c', }; dropdown.menuOptions = - [['a', 'AAA'], ['b', 'BBB'], ['c', 'CCC'], ['d', 'DDD']]; + [{value: 'a', name: 'AAA'}, + {value: 'b', name: 'BBB'}, + {value: 'c', name: 'CCC'}, + {value: 'd', name: 'DDD'}]; Polymer.dom.flush(); // Initially selected item. @@ -84,7 +89,10 @@ value: 'f', }; dropdown.menuOptions = - [['a', 'AAA'], ['b', 'BBB'], ['c', 'CCC'], ['d', 'DDD']]; + [{value: 'a', name: 'AAA'}, + {value: 'b', name: 'BBB'}, + {value: 'c', name: 'CCC'}, + {value: 'd', name: 'DDD'}]; Polymer.dom.flush(); // "Custom" initially selected.
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index 49294bd1..c97017c 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -262,8 +262,7 @@ } void CastContentBrowserClient::AllowCertificateError( - int render_process_id, - int render_view_id, + content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url,
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index 12129e3..d62f0af 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h
@@ -106,8 +106,7 @@ std::string GetApplicationLocale() override; content::QuotaPermissionContext* CreateQuotaPermissionContext() override; void AllowCertificateError( - int render_process_id, - int render_view_id, + content::WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url,
diff --git a/chromecast/chromecast_tests.gypi b/chromecast/chromecast_tests.gypi index b1b3a26..31b69e2 100644 --- a/chromecast/chromecast_tests.gypi +++ b/chromecast/chromecast_tests.gypi
@@ -255,7 +255,7 @@ '../net/net.gyp:net_unittests_apk', '../sql/sql.gyp:sql_unittests_apk', '../sync/sync.gyp:sync_unit_tests_apk', - '../ui/events/events.gyp:events_unittests_apk', + '../ui/events/events_unittests.gyp:events_unittests_apk', '../ui/gfx/gfx_tests.gyp:gfx_unittests_apk', ], 'includes': ['build/tests/test_list.gypi'],
diff --git a/chromecast/media/BUILD.gn b/chromecast/media/BUILD.gn index 2b0e5c82..4c4a87e 100644 --- a/chromecast/media/BUILD.gn +++ b/chromecast/media/BUILD.gn
@@ -58,9 +58,3 @@ "//ui/gfx/geometry", ] } - -# TODO(slan): delete this target once Chromecast M44/earlier is obsolete. -# See: b/21639416 -shared_library("libffmpegsumo") { - output_name = "libffmpegsumo" -}
diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc index f255295..8512370 100644 --- a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc +++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
@@ -376,6 +376,10 @@ } void AudioVideoPipelineDeviceTest::MonitorLoop() { + // Backend is stopped, no need to monitor the loop any more. + if (audio_decoder_ == nullptr && video_decoder_ == nullptr) + return; + base::TimeDelta media_time = base::TimeDelta::FromMicroseconds(backend_->GetCurrentPts());
diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp index d12e47b..2f6fb610 100644 --- a/chromecast/media/media.gyp +++ b/chromecast/media/media.gyp
@@ -14,13 +14,6 @@ ], }, 'targets': [ - # TODO(slan): delete this target once Chromecast M44/earlier is obsolete. - # See: b/21639416 - { - 'target_name': 'libffmpegsumo', - 'type': 'loadable_module', - 'sources': ['empty.cc'], - }, { 'target_name': 'media_audio', 'type': '<(component)',
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 189065b..066edc1e 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -7666.0.0 \ No newline at end of file +7667.0.0 \ No newline at end of file
diff --git a/components/BUILD.gn b/components/BUILD.gn index b24ef8e..caea660 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -42,6 +42,7 @@ "//components/enhanced_bookmarks", "//components/favicon/core", "//components/favicon_base", + "//components/flags_ui", "//components/gcm_driver", "//components/google/core/browser", "//components/history/core/browser", @@ -363,6 +364,7 @@ "//components/enhanced_bookmarks:unit_tests", "//components/favicon/core:unit_tests", "//components/favicon_base:unit_tests", + "//components/flags_ui:unit_tests", "//components/gcm_driver:unit_tests", "//components/google/core/browser:unit_tests", "//components/history/core/browser:unit_tests",
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 962dffd..a0ddd349 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include <algorithm> #include <limits> #include <map> #include <set> @@ -745,16 +746,18 @@ const std::vector<std::string>& form_signatures) { // We obtain the current valid FormStructures represented by // |form_signatures|. We invert both lists because most recent forms are at - // the end of the list. + // the end of the list (and reverse the resulting pointer vector). std::vector<FormStructure*> queried_forms; for (const std::string& signature : base::Reversed(form_signatures)) { for (FormStructure* cur_form : base::Reversed(form_structures_)) { if (cur_form->FormSignature() == signature) { queried_forms.push_back(cur_form); - continue; + break; } } } + std::reverse(queried_forms.begin(), queried_forms.end()); + // If there are no current forms corresponding to the queried signatures, drop // the query response. if (queried_forms.empty())
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 648b2d3..ce33982 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -2605,8 +2605,28 @@ form_structure->DetermineHeuristicTypes(); autofill_manager_->AddSeenForm(form_structure); + // Similarly, a second form. + FormData form2; + form2.name = ASCIIToUTF16("MyForm"); + form2.origin = GURL("http://myform.com/form.html"); + form2.action = GURL("http://myform.com/submit.html"); + + FormFieldData field; + test::CreateTestFormField("Last Name", "lastname", "", "text", &field); + form2.fields.push_back(field); + + test::CreateTestFormField("Middle Name", "middlename", "", "text", &field); + form2.fields.push_back(field); + + test::CreateTestFormField("Postal Code", "zipcode", "", "text", &field); + form2.fields.push_back(field); + + TestFormStructure* form_structure2 = new TestFormStructure(form2); + form_structure2->DetermineHeuristicTypes(); + autofill_manager_->AddSeenForm(form_structure2); + std::string xml = "<autofillqueryresponse>" - "<field autofilltype=\"3\" />" // This is tested below. + "<field autofilltype=\"3\" />" // First test form. "<field autofilltype=\"0\" />" "<field autofilltype=\"0\" />" "<field autofilltype=\"0\" />" @@ -2617,9 +2637,13 @@ "<field autofilltype=\"3\" />" "<field autofilltype=\"2\" />" "<field autofilltype=\"61\"/>" + "<field autofilltype=\"5\" />" // Second form. + "<field autofilltype=\"4\" />" + "<field autofilltype=\"35\"/>" "</autofillqueryresponse>"; std::vector<std::string> signatures; signatures.push_back(form_structure->FormSignature()); + signatures.push_back(form_structure2->FormSignature()); base::HistogramTester histogram_tester; autofill_manager_->OnLoadedServerPredictions(xml, signatures); @@ -2630,8 +2654,15 @@ histogram_tester.ExpectBucketCount("Autofill.ServerQueryResponse", AutofillMetrics::QUERY_RESPONSE_PARSED, 1); - // We expect the server type to have been applied to the first field. + // We expect the server type to have been applied to the first field of the + // first form. EXPECT_EQ(NAME_FIRST, form_structure->field(0)->Type().GetStorableType()); + + // We expect the server types to have been applied to the second form. + EXPECT_EQ(NAME_LAST, form_structure2->field(0)->Type().GetStorableType()); + EXPECT_EQ(NAME_MIDDLE, form_structure2->field(1)->Type().GetStorableType()); + EXPECT_EQ(ADDRESS_HOME_ZIP, + form_structure2->field(2)->Type().GetStorableType()); } // Test that OnLoadedServerPredictions does not call ParseQueryResponse if the
diff --git a/components/autofill/core/browser/autofill_xml_parser_unittest.cc b/components/autofill/core/browser/autofill_xml_parser_unittest.cc index b97c774..929b4759 100644 --- a/components/autofill/core/browser/autofill_xml_parser_unittest.cc +++ b/components/autofill/core/browser/autofill_xml_parser_unittest.cc
@@ -17,7 +17,7 @@ class AutofillQueryXmlParserTest : public testing::Test { public: - AutofillQueryXmlParserTest(): upload_required_(USE_UPLOAD_RATES) {}; + AutofillQueryXmlParserTest(): upload_required_(USE_UPLOAD_RATES) {} ~AutofillQueryXmlParserTest() override{}; protected: @@ -36,7 +36,7 @@ class AutofillUploadXmlParserTest : public testing::Test { public: - AutofillUploadXmlParserTest(): positive_(0), negative_(0) {}; + AutofillUploadXmlParserTest(): positive_(0), negative_(0) {} ~AutofillUploadXmlParserTest() override{}; protected: @@ -160,7 +160,7 @@ EXPECT_EQ(NO_SERVER_DATA, field_infos_[0].field_type); } -// Test successfull upload response. +// Test successful upload response. TEST_F(AutofillUploadXmlParserTest, TestSuccessfulResponse) { ParseUploadXML("<autofilluploadresponse positiveuploadrate=\"0.5\" " "negativeuploadrate=\"0.3\"/>",
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 61cf0461..2a5c13b 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -206,6 +206,9 @@ 'favicon/core/favicon_handler_unittest.cc', 'favicon/core/large_icon_service_unittest.cc', ], + 'flags_ui_unittest_sources': [ + 'flags_ui/flags_state_unittest.cc', + ], 'undo_unittest_sources': [ 'undo/bookmark_undo_service_test.cc', 'undo/undo_manager_test.cc', @@ -880,6 +883,7 @@ '<@(enhanced_bookmarks_unittest_sources)', '<@(favicon_base_unittest_sources)', '<@(favicon_unittest_sources)', + '<@(flags_ui_unittest_sources)', '<@(gcm_driver_crypto_unittest_sources)', '<@(gcm_driver_unittest_sources)', '<@(google_unittest_sources)', @@ -989,6 +993,7 @@ 'components.gyp:enhanced_bookmarks_test_support', 'components.gyp:favicon_base', 'components.gyp:favicon_core', + 'components.gyp:flags_ui', 'components.gyp:gcm_driver', 'components.gyp:gcm_driver_test_support', 'components.gyp:google_core_browser',
diff --git a/components/crash/content/app/crashpad_mac.mm b/components/crash/content/app/crashpad_mac.mm index bee4aad..f87fc96e 100644 --- a/components/crash/content/app/crashpad_mac.mm +++ b/components/crash/content/app/crashpad_mac.mm
@@ -153,7 +153,7 @@ url, process_annotations, arguments, - false); + true); if (result) { result = crashpad_client.UseHandler(); }
diff --git a/components/crash/content/browser/crash_dump_manager_android.cc b/components/crash/content/browser/crash_dump_manager_android.cc index 1b60e20..62e77ad 100644 --- a/components/crash/content/browser/crash_dump_manager_android.cc +++ b/components/crash/content/browser/crash_dump_manager_android.cc
@@ -8,7 +8,6 @@ #include "base/files/file_util.h" #include "base/format_macros.h" #include "base/logging.h" -#include "base/metrics/histogram_macros.h" #include "base/posix/global_descriptors.h" #include "base/process/process.h" #include "base/rand_util.h" @@ -82,12 +81,8 @@ } // static -void CrashDumpManager::ProcessMinidump( - const base::FilePath& minidump_path, - base::ProcessHandle pid, - content::ProcessType process_type, - base::TerminationStatus exit_status, - base::android::ApplicationState app_state) { +void CrashDumpManager::ProcessMinidump(const base::FilePath& minidump_path, + base::ProcessHandle pid) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); CHECK(instance_); int64 file_size = 0; @@ -95,35 +90,6 @@ DCHECK(r) << "Failed to retrieve size for minidump " << minidump_path.value(); - if (process_type == content::PROCESS_TYPE_RENDERER && - exit_status == base::TERMINATION_STATUS_OOM_PROTECTED) { - bool is_running = - (app_state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); - bool is_paused = - (app_state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES); - ExitStatus renderer_exit_status; - if (file_size == 0) { - if (is_running) { - renderer_exit_status = EMPTY_MINIDUMP_WHILE_RUNNING; - } else if (is_paused) { - renderer_exit_status = EMPTY_MINIDUMP_WHILE_PAUSED; - } else { - renderer_exit_status = EMPTY_MINIDUMP_WHILE_BACKGROUND; - } - } else { - if (is_running) { - renderer_exit_status = VALID_MINIDUMP_WHILE_RUNNING; - } else if (is_paused) { - renderer_exit_status = VALID_MINIDUMP_WHILE_PAUSED; - } else { - renderer_exit_status = VALID_MINIDUMP_WHILE_BACKGROUND; - } - } - UMA_HISTOGRAM_ENUMERATION("Tab.RendererDetailedExitStatus", - renderer_exit_status, - ExitStatus::COUNT); - } - if (file_size == 0) { // Empty minidump, this process did not crash. Just remove the file. r = base::DeleteFile(minidump_path, false); @@ -156,21 +122,13 @@ void CrashDumpManager::BrowserChildProcessHostDisconnected( const content::ChildProcessData& data) { - OnChildExit(data.id, - data.handle, - static_cast<content::ProcessType>(data.process_type), - /* exit_status */ base::TERMINATION_STATUS_MAX_ENUM, - /* app_state */ base::android::APPLICATION_STATE_UNKNOWN); + OnChildExit(data.id, data.handle); } void CrashDumpManager::BrowserChildProcessCrashed( const content::ChildProcessData& data, int exit_code) { - OnChildExit(data.id, - data.handle, - static_cast<content::ProcessType>(data.process_type), - /* exit_status */ base::TERMINATION_STATUS_ABNORMAL_TERMINATION, - /* app_state */ base::android::APPLICATION_STATE_UNKNOWN); + OnChildExit(data.id, data.handle); } void CrashDumpManager::Observe(int type, @@ -184,14 +142,7 @@ case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { content::RenderProcessHost* rph = content::Source<content::RenderProcessHost>(source).ptr(); - content::RenderProcessHost::RendererClosedDetails* process_details = - content::Details<content::RenderProcessHost::RendererClosedDetails>( - details).ptr(); - OnChildExit(rph->GetID(), - rph->GetHandle(), - content::PROCESS_TYPE_RENDERER, - process_details->status, - base::android::ApplicationStatusListener::GetState()); + OnChildExit(rph->GetID(), rph->GetHandle()); break; } default: @@ -201,10 +152,7 @@ } void CrashDumpManager::OnChildExit(int child_process_id, - base::ProcessHandle pid, - content::ProcessType process_type, - base::TerminationStatus exit_status, - base::android::ApplicationState app_state) { + base::ProcessHandle pid) { base::FilePath minidump_path; { base::AutoLock auto_lock(child_process_id_to_minidump_path_lock_); @@ -220,12 +168,7 @@ } BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - base::Bind(&CrashDumpManager::ProcessMinidump, - minidump_path, - pid, - process_type, - exit_status, - app_state)); + base::Bind(&CrashDumpManager::ProcessMinidump, minidump_path, pid)); } } // namespace breakpad
diff --git a/components/crash/content/browser/crash_dump_manager_android.h b/components/crash/content/browser/crash_dump_manager_android.h index bad3fb3..e3f2391e 100644 --- a/components/crash/content/browser/crash_dump_manager_android.h +++ b/components/crash/content/browser/crash_dump_manager_android.h
@@ -7,16 +7,13 @@ #include <map> -#include "base/android/application_status_listener.h" #include "base/files/file.h" #include "base/files/file_path.h" -#include "base/process/kill.h" #include "base/process/process.h" #include "base/synchronization/lock.h" #include "content/public/browser/browser_child_process_observer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "content/public/common/process_type.h" namespace content { class RenderProcessHost; @@ -51,23 +48,8 @@ private: typedef std::map<int, base::FilePath> ChildProcessIDToMinidumpPath; - // This enum is used to back a UMA histogram, and must be treated as - // append-only. - enum ExitStatus { - EMPTY_MINIDUMP_WHILE_RUNNING = 0, - EMPTY_MINIDUMP_WHILE_PAUSED = 1, - EMPTY_MINIDUMP_WHILE_BACKGROUND = 2, - VALID_MINIDUMP_WHILE_RUNNING = 3, - VALID_MINIDUMP_WHILE_PAUSED = 4, - VALID_MINIDUMP_WHILE_BACKGROUND = 5, - COUNT = 6 - }; - static void ProcessMinidump(const base::FilePath& minidump_path, - base::ProcessHandle pid, - content::ProcessType process_type, - base::TerminationStatus exit_status, - base::android::ApplicationState app_state); + base::ProcessHandle pid); // content::BrowserChildProcessObserver implementation: void BrowserChildProcessHostDisconnected( @@ -82,11 +64,7 @@ const content::NotificationDetails& details) override; // Called on child process exit (including crash). - void OnChildExit(int child_process_id, - base::ProcessHandle pid, - content::ProcessType process_type, - base::TerminationStatus exit_status, - base::android::ApplicationState app_state); + void OnChildExit(int child_process_id, base::ProcessHandle pid); content::NotificationRegistrar notification_registrar_;
diff --git a/components/cronet/android/cronet_library_loader.cc b/components/cronet/android/cronet_library_loader.cc index fec9360..c0891dc 100644 --- a/components/cronet/android/cronet_library_loader.cc +++ b/components/cronet/android/cronet_library_loader.cc
@@ -86,13 +86,6 @@ base::android::LibraryLoaderExitHook(); } -void CronetInitApplicationContext(JNIEnv* env, - const JavaParamRef<jclass>& jcaller, - const JavaParamRef<jobject>& japp_context) { - // Set application context. - base::android::InitApplicationContext(env, japp_context); -} - void CronetInitOnMainThread(JNIEnv* env, const JavaParamRef<jclass>& jcaller) { #if !defined(USE_ICU_ALTERNATIVES_ON_ANDROID) base::i18n::InitializeICU();
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java b/components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java index 60a7675..e51334e 100644 --- a/components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java +++ b/components/cronet/android/java/src/org/chromium/net/CronetLibraryLoader.java
@@ -8,6 +8,7 @@ import android.os.Handler; import android.os.Looper; +import org.chromium.base.ContextUtils; import org.chromium.base.annotations.JNINamespace; /** @@ -39,7 +40,7 @@ Version.CRONET_VERSION, nativeGetCronetVersion())); } - nativeCronetInitApplicationContext(context.getApplicationContext()); + ContextUtils.initApplicationContext(context.getApplicationContext()); // Init native Chromium CronetEngine on Main UI thread. Runnable task = new Runnable() { public void run() { @@ -75,6 +76,5 @@ // Native methods are implemented in cronet_loader.cc. private static native void nativeCronetInitOnMainThread(); - private static native void nativeCronetInitApplicationContext(Context appContext); private static native String nativeGetCronetVersion(); }
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc index 0132adde..991b00e1e 100644 --- a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc +++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
@@ -4,7 +4,12 @@ #include "components/data_reduction_proxy/content/browser/content_lofi_decider.h" +#include <string> + +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "content/public/browser/resource_request_info.h" +#include "net/http/http_request_headers.h" namespace data_reduction_proxy { @@ -15,8 +20,59 @@ bool ContentLoFiDecider::IsUsingLoFiMode(const net::URLRequest& request) const { const content::ResourceRequestInfo* request_info = content::ResourceRequestInfo::ForRequest(&request); + // The Lo-Fi directive should not be added for users in the Lo-Fi field + // trial "Control" group. Check that the user is in a group that can get + // "q=low". + bool lofi_enabled_via_flag_or_field_trial = + params::IsLoFiOnViaFlags() || params::IsIncludedInLoFiEnabledFieldTrial(); + + // Return if the user is using Lo-Fi and not part of the "Control" group. if (request_info) - return request_info->IsUsingLoFi(); + return request_info->IsUsingLoFi() && lofi_enabled_via_flag_or_field_trial; + return false; +} + +bool ContentLoFiDecider::MaybeAddLoFiDirectiveToHeaders( + const net::URLRequest& request, + net::HttpRequestHeaders* headers) const { + const content::ResourceRequestInfo* request_info = + content::ResourceRequestInfo::ForRequest(&request); + + if (!request_info) + return false; + + // The Lo-Fi directive should not be added for users in the Lo-Fi field + // trial "Control" group. Check that the user is in a group that should + // get "q=low". + bool lofi_enabled_via_flag_or_field_trial = + params::IsLoFiOnViaFlags() || params::IsIncludedInLoFiEnabledFieldTrial(); + + std::string header_value; + + // User is using Lo-Fi and not part of the "Control" group. + if (request_info->IsUsingLoFi() && lofi_enabled_via_flag_or_field_trial) { + if (headers->HasHeader(chrome_proxy_header())) { + headers->GetHeader(chrome_proxy_header(), &header_value); + headers->RemoveHeader(chrome_proxy_header()); + header_value += ", "; + } + header_value += chrome_proxy_lo_fi_directive(); + headers->SetHeader(chrome_proxy_header(), header_value); + return true; + } + + // User is part of Lo-Fi active control experiment. + if (request_info->IsUsingLoFi() && + params::IsIncludedInLoFiControlFieldTrial()) { + if (headers->HasHeader(chrome_proxy_header())) { + headers->GetHeader(chrome_proxy_header(), &header_value); + headers->RemoveHeader(chrome_proxy_header()); + header_value += ", "; + } + header_value += chrome_proxy_lo_fi_experiment_directive(); + headers->SetHeader(chrome_proxy_header(), header_value); + } + return false; }
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.h b/components/data_reduction_proxy/content/browser/content_lofi_decider.h index 222fedd..01e0377 100644 --- a/components/data_reduction_proxy/content/browser/content_lofi_decider.h +++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.h
@@ -9,6 +9,7 @@ #include "base/macros.h" namespace net { +class HttpRequestHeaders; class URLRequest; } @@ -17,14 +18,19 @@ // Class responsible for deciding whether a request should be requested with low // fidelity (Lo-Fi) or not. Relies on the Lo-Fi mode state stored in the // request's content::ResourceRequestInfo, which must be fetched using -// content::ResourceRequestInfo::ForRequest. Owned by DataReductionProxyIOData -// and should be called on the IO thread. +// content::ResourceRequestInfo::ForRequest. Lo-Fi mode will not be enabled for +// requests that don't have a ResourceRequestInfo, such as background requests. +// Owned by DataReductionProxyIOData and should be called on the IO thread. class ContentLoFiDecider : public LoFiDecider { public: ContentLoFiDecider(); ~ContentLoFiDecider() override; + // LoFiDecider implementation: bool IsUsingLoFiMode(const net::URLRequest& request) const override; + bool MaybeAddLoFiDirectiveToHeaders( + const net::URLRequest& request, + net::HttpRequestHeaders* headers) const override; private: DISALLOW_COPY_AND_ASSIGN(ContentLoFiDecider);
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc index b8d14c0..7ccb4c9 100644 --- a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc +++ b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
@@ -13,6 +13,7 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" @@ -29,8 +30,6 @@ namespace { -const char kChromeProxyHeader[] = "chrome-proxy"; - #if defined(OS_ANDROID) const Client kClient = Client::CHROME_ANDROID; #elif defined(OS_IOS) @@ -119,11 +118,23 @@ static void VerifyLoFiHeader(bool expected_lofi_used, const net::HttpRequestHeaders& headers) { - EXPECT_TRUE(headers.HasHeader(kChromeProxyHeader)); + EXPECT_TRUE(headers.HasHeader(chrome_proxy_header())); std::string header_value; - headers.GetHeader(kChromeProxyHeader, &header_value); - EXPECT_EQ(expected_lofi_used, - header_value.find("q=low") != std::string::npos); + headers.GetHeader(chrome_proxy_header(), &header_value); + EXPECT_EQ( + expected_lofi_used, + header_value.find(chrome_proxy_lo_fi_directive()) != std::string::npos); + } + + static void VerifyLoFiExperimentHeader( + bool expected_lofi_experiment_used, + const net::HttpRequestHeaders& headers) { + EXPECT_TRUE(headers.HasHeader(chrome_proxy_header())); + std::string header_value; + headers.GetHeader(chrome_proxy_header(), &header_value); + EXPECT_EQ(expected_lofi_experiment_used, + header_value.find(chrome_proxy_lo_fi_experiment_directive()) != + std::string::npos); } protected: @@ -222,4 +233,104 @@ } } +TEST_F(ContentLoFiDeciderTest, AutoLoFi) { + const struct { + bool auto_lofi_enabled_group; + bool auto_lofi_control_group; + bool network_prohibitively_slow; + } tests[] = { + {false, false, false}, + {false, false, true}, + {true, false, false}, + {true, false, true}, + {false, true, false}, + {false, true, true}, + // Repeat this test data to simulate user moving out of Lo-Fi control + // experiment. + {false, true, false}, + }; + + for (size_t i = 0; i < arraysize(tests); ++i) { + test_context_->config()->ResetLoFiStatusForTest(); + // Lo-Fi header is expected only if session is part of Lo-Fi enabled field + // trial and network is prohibitively slow. + bool expect_lofi_header = + tests[i].auto_lofi_enabled_group && tests[i].network_prohibitively_slow; + bool expect_lofi_experiment_header = + tests[i].auto_lofi_control_group && tests[i].network_prohibitively_slow; + + base::FieldTrialList field_trial_list(nullptr); + if (tests[i].auto_lofi_enabled_group) { + base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(), + "Enabled"); + } + + if (tests[i].auto_lofi_control_group) { + base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(), + "Control"); + } + + test_context_->config()->SetNetworkProhibitivelySlow( + tests[i].network_prohibitively_slow); + + scoped_ptr<net::URLRequest> request = + CreateRequest(tests[i].network_prohibitively_slow); + net::HttpRequestHeaders headers; + NotifyBeforeSendProxyHeaders(&headers, request.get()); + + VerifyLoFiHeader(expect_lofi_header, headers); + VerifyLoFiExperimentHeader(expect_lofi_experiment_header, headers); + } +} + +TEST_F(ContentLoFiDeciderTest, SlowConnectionsFlag) { + const struct { + bool slow_connections_flag_enabled; + bool network_prohibitively_slow; + bool auto_lofi_enabled_group; + + } tests[] = { + {false, false, false}, {false, true, false}, {true, false, false}, + {true, true, false}, {false, false, true}, {false, true, true}, + {true, false, true}, {true, true, true}, + }; + + for (size_t i = 0; i < arraysize(tests); ++i) { + test_context_->config()->ResetLoFiStatusForTest(); + // For the purpose of this test, Lo-Fi header is expected only if LoFi Slow + // Connection Flag is enabled or session is part of Lo-Fi enabled field + // trial. For both cases, an additional condition is that network must be + // prohibitively slow. + bool expect_lofi_header = (tests[i].slow_connections_flag_enabled && + tests[i].network_prohibitively_slow) || + (!tests[i].slow_connections_flag_enabled && + tests[i].auto_lofi_enabled_group && + tests[i].network_prohibitively_slow); + + std::string expected_header; + + if (tests[i].slow_connections_flag_enabled) { + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kDataReductionProxyLoFi, + switches::kDataReductionProxyLoFiValueSlowConnectionsOnly); + } + + base::FieldTrialList field_trial_list(nullptr); + if (tests[i].auto_lofi_enabled_group) { + base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(), + "Enabled"); + } + + test_context_->config()->SetNetworkProhibitivelySlow( + tests[i].network_prohibitively_slow); + + scoped_ptr<net::URLRequest> request = + CreateRequest(tests[i].network_prohibitively_slow); + net::HttpRequestHeaders headers; + NotifyBeforeSendProxyHeaders(&headers, request.get()); + + VerifyLoFiHeader(expect_lofi_header, headers); + } +} + } // namespace data_reduction_roxy
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 9b3a9b6a..5fd509f 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
@@ -174,12 +174,11 @@ net::HttpRequestHeaders* headers) { DCHECK(data_reduction_proxy_config_); - bool is_using_lofi_mode = false; - if (data_reduction_proxy_io_data_ && data_reduction_proxy_io_data_->lofi_decider() && request) { LoFiDecider* lofi_decider = data_reduction_proxy_io_data_->lofi_decider(); - is_using_lofi_mode = lofi_decider->IsUsingLoFiMode(*request); + bool is_using_lofi_mode = + lofi_decider->MaybeAddLoFiDirectiveToHeaders(*request, headers); if ((request->load_flags() & net::LOAD_MAIN_FRAME) != 0) { // TODO(megjablon): Need to switch to per page. @@ -190,7 +189,7 @@ if (data_reduction_proxy_request_options_) { data_reduction_proxy_request_options_->MaybeAddRequestHeader( - request, proxy_info.proxy_server(), headers, is_using_lofi_mode); + request, proxy_info.proxy_server(), headers); } }
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 b27e414b..3232d55 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
@@ -83,6 +83,27 @@ should_request_lofi_resource_ = should_request_lofi_resource; } + bool MaybeAddLoFiDirectiveToHeaders( + const net::URLRequest& request, + net::HttpRequestHeaders* headers) const override { + if (should_request_lofi_resource_) { + const char kChromeProxyHeader[] = "Chrome-Proxy"; + std::string header_value; + + if (headers->HasHeader(kChromeProxyHeader)) { + headers->GetHeader(kChromeProxyHeader, &header_value); + headers->RemoveHeader(kChromeProxyHeader); + header_value += ", "; + } + + header_value += "q=low"; + headers->SetHeader(kChromeProxyHeader, header_value); + return true; + } + + return false; + } + private: bool should_request_lofi_resource_; };
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 fbd30d7..89276ff8 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
@@ -125,6 +125,7 @@ // Add any new data reduction proxy prefs to the |pref_map_| or the // |list_pref_map_| in Init() of DataReductionProxyCompressionStats. void RegisterPrefs(PrefRegistrySimple* registry) { + registry->RegisterStringPref(prefs::kDataReductionProxy, std::string()); registry->RegisterInt64Pref( prefs::kHttpReceivedContentLength, 0); registry->RegisterInt64Pref(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc index dc173f5..01cc7bca 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
@@ -48,9 +48,7 @@ const char kBuildNumberHeaderOption[] = "b"; const char kPatchNumberHeaderOption[] = "p"; const char kClientHeaderOption[] = "c"; -const char kLoFiHeaderOption[] = "q"; const char kExperimentsOption[] = "exp"; -const char kLoFiExperimentID[] = "lofi_active_control"; // The empty version for the authentication protocol. Currently used by // Android webview. @@ -160,56 +158,6 @@ RegenerateRequestHeaderValue(); } -void DataReductionProxyRequestOptions::MayRegenerateHeaderBasedOnLoFi( - bool is_using_lofi_mode) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // The Lo-Fi directive should not be added for users in the Lo-Fi field - // trial "Control" group. Check that the user is in a group that should - // get "q=low". - bool lofi_enabled_via_flag_or_field_trial = - params::IsLoFiOnViaFlags() || params::IsIncludedInLoFiEnabledFieldTrial(); - - // Lo-Fi was not enabled, but now is. Add the header option. - if (lofi_.empty() && is_using_lofi_mode && - lofi_enabled_via_flag_or_field_trial) { - lofi_ = "low"; - RegenerateRequestHeaderValue(); - return; - } - - // Lo-Fi was enabled, but no longer is. Remove the header option. - if (!lofi_.empty() && - (!is_using_lofi_mode || !lofi_enabled_via_flag_or_field_trial)) { - lofi_ = std::string(); - RegenerateRequestHeaderValue(); - return; - } - - // User was not part of Lo-Fi active control experiment, but now is. - if (std::find(experiments_.begin(), experiments_.end(), - std::string(kLoFiExperimentID)) == experiments_.end() && - is_using_lofi_mode && params::IsIncludedInLoFiControlFieldTrial()) { - experiments_.push_back(kLoFiExperimentID); - RegenerateRequestHeaderValue(); - DCHECK(std::find(experiments_.begin(), experiments_.end(), - kLoFiExperimentID) != experiments_.end()); - return; - } - - // User was part of Lo-Fi active control experiment, but now is not. - auto it = std::find(experiments_.begin(), experiments_.end(), - std::string(kLoFiExperimentID)); - if (it != experiments_.end() && - (!is_using_lofi_mode || !params::IsIncludedInLoFiControlFieldTrial())) { - experiments_.erase(it); - RegenerateRequestHeaderValue(); - DCHECK(std::find(experiments_.begin(), experiments_.end(), - std::string(kLoFiExperimentID)) == experiments_.end()); - return; - } -} - void DataReductionProxyRequestOptions::UpdateExperiments() { std::string experiments = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( @@ -249,34 +197,30 @@ void DataReductionProxyRequestOptions::MaybeAddRequestHeader( net::URLRequest* request, const net::ProxyServer& proxy_server, - net::HttpRequestHeaders* request_headers, - bool is_using_lofi_mode) { + net::HttpRequestHeaders* request_headers) { DCHECK(thread_checker_.CalledOnValidThread()); if (!proxy_server.is_valid()) return; if (proxy_server.is_direct()) return; MaybeAddRequestHeaderImpl(request, proxy_server.host_port_pair(), false, - request_headers, is_using_lofi_mode); + request_headers); } void DataReductionProxyRequestOptions::MaybeAddProxyTunnelRequestHandler( const net::HostPortPair& proxy_server, net::HttpRequestHeaders* request_headers) { DCHECK(thread_checker_.CalledOnValidThread()); - MaybeAddRequestHeaderImpl(nullptr, proxy_server, true, request_headers, - false); + MaybeAddRequestHeaderImpl(nullptr, proxy_server, true, request_headers); } void DataReductionProxyRequestOptions::SetHeader( const net::URLRequest* request, - net::HttpRequestHeaders* headers, - bool is_using_lofi_mode) { + net::HttpRequestHeaders* headers) { base::Time now = Now(); // Authorization credentials must be regenerated if they are expired. if (!use_assigned_credentials_ && (now > credentials_expiration_time_)) UpdateCredentials(); - MayRegenerateHeaderBasedOnLoFi(is_using_lofi_mode); const char kChromeProxyHeader[] = "Chrome-Proxy"; std::string header_value; if (headers->HasHeader(kChromeProxyHeader)) { @@ -395,14 +339,13 @@ const net::URLRequest* request, const net::HostPortPair& proxy_server, bool expect_ssl, - net::HttpRequestHeaders* request_headers, - bool is_using_lofi_mode) { + net::HttpRequestHeaders* request_headers) { if (proxy_server.IsEmpty()) return; if (data_reduction_proxy_config_->IsDataReductionProxy(proxy_server, NULL) && data_reduction_proxy_config_->UsingHTTPTunnel(proxy_server) == expect_ssl) { - SetHeader(request, request_headers, is_using_lofi_mode); + SetHeader(request, request_headers); } } @@ -422,8 +365,6 @@ headers.push_back(FormatOption(kBuildNumberHeaderOption, build_)); headers.push_back(FormatOption(kPatchNumberHeaderOption, patch_)); } - if (!lofi_.empty()) - headers.push_back(FormatOption(kLoFiHeaderOption, lofi_)); for (const auto& experiment : experiments_) headers.push_back(FormatOption(kExperimentsOption, experiment));
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h index 28f1c7a9..3f592c8 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
@@ -29,9 +29,7 @@ extern const char kBuildNumberHeaderOption[]; extern const char kPatchNumberHeaderOption[]; extern const char kClientHeaderOption[]; -extern const char kLoFiHeaderOption[]; extern const char kExperimentsOption[]; -extern const char kLoFiExperimentID[]; #if defined(OS_ANDROID) extern const char kAndroidWebViewProtocolVersion[]; @@ -94,14 +92,12 @@ void Init(); // Adds a 'Chrome-Proxy' header to |request_headers| with the data reduction - // proxy authentication credentials. If |is_using_lofi_mode| is true - // adds the "q=low" directive to the header. Only adds this header if the + // proxy authentication credentials. Only adds this header if the // provided |proxy_server| is a data reduction proxy and not the data // reduction proxy's CONNECT server. void MaybeAddRequestHeader(net::URLRequest* request, const net::ProxyServer& proxy_server, - net::HttpRequestHeaders* request_headers, - bool is_using_lofi_mode); + net::HttpRequestHeaders* request_headers); // Adds a 'Chrome-Proxy' header to |request_headers| with the data reduction // proxy authentication credentials. Only adds this header if the provided @@ -139,8 +135,7 @@ protected: void SetHeader(const net::URLRequest* request, - net::HttpRequestHeaders* headers, - bool is_using_lofi_mode); + net::HttpRequestHeaders* headers); // Returns a UTF16 string that's the hash of the configured authentication // |key| and |salt|. Returns an empty UTF16 string if no key is configured or @@ -175,9 +170,6 @@ // Updates client type, build, and patch. void UpdateVersion(); - // May regenerate the Chrome Proxy header based on changes in Lo-Fi status. - void MayRegenerateHeaderBasedOnLoFi(bool is_using_lofi_mode); - // Update the value of the experiments to be run and regenerate the header if // necessary. void UpdateExperiments(); @@ -194,13 +186,11 @@ // Adds authentication headers only if |expects_ssl| is true and // |proxy_server| is a data reduction proxy used for ssl tunneling via // HTTP CONNECT, or |expect_ssl| is false and |proxy_server| is a data - // reduction proxy for HTTP traffic. If |is_using_lofi_mode| is true adds the - // "q=low" directive to the header. + // reduction proxy for HTTP traffic. void MaybeAddRequestHeaderImpl(const net::URLRequest* request, const net::HostPortPair& proxy_server, bool expect_ssl, - net::HttpRequestHeaders* request_headers, - bool is_using_lofi_mode); + net::HttpRequestHeaders* request_headers); // Regenerates the |header_value_| string which is concatenated to the // Chrome-proxy header. @@ -220,7 +210,6 @@ std::string secure_session_; std::string build_; std::string patch_; - std::string lofi_; std::vector<std::string> experiments_; // The time at which the session expires. Used to ensure that a session is
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 cbc3b44..3b0cd6c 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
@@ -93,7 +93,6 @@ const std::string& client, const std::string& build, const std::string& patch, - const std::string& lofi, const std::vector<std::string> experiments, std::string* expected_header) { std::vector<std::string> expected_options; @@ -121,10 +120,6 @@ expected_options.push_back( std::string(kPatchNumberHeaderOption) + "=" + patch); } - if (!lofi.empty()) { - expected_options.push_back( - std::string(kLoFiHeaderOption) + "=" + lofi); - } for (const auto& experiment : experiments) { expected_options.push_back( std::string(kExperimentsOption) + "=" + experiment); @@ -172,8 +167,7 @@ } void VerifyExpectedHeader(const std::string& proxy_uri, - const std::string& expected_header, - bool should_request_lofi_resource) { + const std::string& expected_header) { test_context_->RunUntilIdle(); net::HttpRequestHeaders headers; request_options_->MaybeAddRequestHeader( @@ -181,7 +175,7 @@ proxy_uri.empty() ? net::ProxyServer() : net::ProxyServer::FromURI( proxy_uri, net::ProxyServer::SCHEME_HTTP), - &headers, should_request_lofi_resource); + &headers); if (expected_header.empty()) { EXPECT_FALSE(headers.HasHeader(kChromeProxyHeader)); return; @@ -211,15 +205,13 @@ std::string expected_header; SetHeaderExpectations(kExpectedSession2, kExpectedCredentials2, std::string(), kClientStr, kExpectedBuild, kExpectedPatch, - std::string(), std::vector<std::string>(), - &expected_header); + std::vector<std::string>(), &expected_header); std::string expected_header2; SetHeaderExpectations("86401-1633771873-1633771873-1633771873", "d7c1c34ef6b90303b01c48a6c1db6419", std::string(), kClientStr, kExpectedBuild, kExpectedPatch, - std::string(), std::vector<std::string>(), - &expected_header2); + std::vector<std::string>(), &expected_header2); CreateRequestOptions(kVersion); test_context_->RunUntilIdle(); @@ -228,16 +220,16 @@ request_options()->SetKeyOnIO(kTestKey2); // Don't write headers if the proxy is invalid. - VerifyExpectedHeader(std::string(), std::string(), false); + VerifyExpectedHeader(std::string(), std::string()); // Don't write headers with a valid proxy, that's not a data reduction proxy. - VerifyExpectedHeader(kOtherProxy, std::string(), false); + VerifyExpectedHeader(kOtherProxy, std::string()); // Don't write headers with a valid data reduction ssl proxy. - VerifyExpectedHeader(params()->DefaultSSLOrigin(), std::string(), false); + VerifyExpectedHeader(params()->DefaultSSLOrigin(), std::string()); // Write headers with a valid data reduction proxy. - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header, false); + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); // Write headers with a valid data reduction ssl proxy when one is expected. net::HttpRequestHeaders ssl_headers; @@ -253,227 +245,49 @@ // Fast forward 24 hours. The header should be the same. request_options()->set_offset(base::TimeDelta::FromSeconds(24 * 60 * 60)); - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header, false); + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); // Fast forward one more second. The header should be new. request_options()->set_offset(base::TimeDelta::FromSeconds(24 * 60 * 60 + 1)); - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header2, false); + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header2); } TEST_F(DataReductionProxyRequestOptionsTest, AuthorizationIgnoresEmptyKey) { std::string expected_header; SetHeaderExpectations(kExpectedSession, kExpectedCredentials, std::string(), kClientStr, kExpectedBuild, kExpectedPatch, - std::string(), std::vector<std::string>(), - &expected_header); + std::vector<std::string>(), &expected_header); CreateRequestOptions(kVersion); - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header, false); + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); // Now set an empty key. The auth handler should ignore that, and the key // remains |kTestKey|. request_options()->SetKeyOnIO(std::string()); - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header, false); + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); } TEST_F(DataReductionProxyRequestOptionsTest, AuthorizationBogusVersion) { std::string expected_header; SetHeaderExpectations(kExpectedSession2, kExpectedCredentials2, std::string(), - kClientStr, std::string(), std::string(), std::string(), + kClientStr, std::string(), std::string(), std::vector<std::string>(), &expected_header); CreateRequestOptions(kBogusVersion); // Now set a key. request_options()->SetKeyOnIO(kTestKey2); - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header, false); -} - -TEST_F(DataReductionProxyRequestOptionsTest, LoFiOnThroughCommandLineSwitch) { - test_context_->config()->ResetLoFiStatusForTest(); - std::string expected_header; - SetHeaderExpectations(kExpectedSession, kExpectedCredentials, std::string(), - kClientStr, std::string(), std::string(), std::string(), - std::vector<std::string>(), &expected_header); - CreateRequest(); - CreateRequestOptions(kBogusVersion); - VerifyExpectedHeader( - params()->DefaultOrigin(), expected_header, - test_context_->config()->ShouldEnableLoFiMode(request())); - - test_context_->config()->ResetLoFiStatusForTest(); - // Add the LoFi command line switch. - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kDataReductionProxyLoFi, - switches::kDataReductionProxyLoFiValueAlwaysOn); - - SetHeaderExpectations(kExpectedSession, kExpectedCredentials, std::string(), - kClientStr, std::string(), std::string(), "low", - std::vector<std::string>(), &expected_header); - - CreateRequestOptions(kBogusVersion); - VerifyExpectedHeader( - params()->DefaultOrigin(), expected_header, - test_context_->config()->ShouldEnableLoFiMode(request())); -} - -TEST_F(DataReductionProxyRequestOptionsTest, AutoLoFi) { - const struct { - bool auto_lofi_enabled_group; - bool auto_lofi_control_group; - bool network_prohibitively_slow; - } tests[] = { - {false, false, false}, - {false, false, true}, - {true, false, false}, - {true, false, true}, - {false, true, false}, - {false, true, true}, - // Repeat this test data to simulate user moving out of Lo-Fi control - // experiment. - {false, true, false}, - }; - - for (size_t i = 0; i < arraysize(tests); ++i) { - test_context_->config()->ResetLoFiStatusForTest(); - // Lo-Fi header is expected only if session is part of Lo-Fi enabled field - // trial and network is prohibitively slow. - bool expect_lofi_header = - tests[i].auto_lofi_enabled_group && tests[i].network_prohibitively_slow; - bool expect_lofi_experiment_header = - tests[i].auto_lofi_control_group && tests[i].network_prohibitively_slow; - - std::string expected_header; - if (!expect_lofi_header) { - SetHeaderExpectations(kExpectedSession, kExpectedCredentials, - std::string(), kClientStr, std::string(), - std::string(), std::string(), - std::vector<std::string>(), &expected_header); - } else { - SetHeaderExpectations(kExpectedSession, kExpectedCredentials, - std::string(), kClientStr, std::string(), - std::string(), "low", std::vector<std::string>(), - &expected_header); - } - - if (expect_lofi_experiment_header) { - expected_header = expected_header.append(", exp="); - expected_header = expected_header.append(kLoFiExperimentID); - } - - base::FieldTrialList field_trial_list(nullptr); - if (tests[i].auto_lofi_enabled_group) { - base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(), - "Enabled"); - } - - if (tests[i].auto_lofi_control_group) { - base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(), - "Control"); - } - - test_context_->config()->SetNetworkProhibitivelySlow( - tests[i].network_prohibitively_slow); - - CreateRequest(); - - CreateRequestOptions(kBogusVersion); - VerifyExpectedHeader( - params()->DefaultOrigin(), expected_header, - test_context_->config()->ShouldEnableLoFiMode(request())); - } -} - -TEST_F(DataReductionProxyRequestOptionsTest, SlowConnectionsFlag) { - const struct { - bool slow_connections_flag_enabled; - bool network_prohibitively_slow; - bool auto_lofi_enabled_group; - - } tests[] = { - { - false, false, false, - }, - { - false, true, false, - }, - { - true, false, false, - }, - { - true, true, false, - }, - { - false, false, true, - }, - { - false, true, true, - }, - { - true, false, true, - }, - { - true, true, true, - }, - }; - - for (size_t i = 0; i < arraysize(tests); ++i) { - test_context_->config()->ResetLoFiStatusForTest(); - // For the purpose of this test, Lo-Fi header is expected only if LoFi Slow - // Connection Flag is enabled or session is part of Lo-Fi enabled field - // trial. For both cases, an additional condition is that network must be - // prohibitively slow. - bool expect_lofi_header = (tests[i].slow_connections_flag_enabled && - tests[i].network_prohibitively_slow) || - (!tests[i].slow_connections_flag_enabled && - tests[i].auto_lofi_enabled_group && - tests[i].network_prohibitively_slow); - - std::string expected_header; - if (!expect_lofi_header) { - SetHeaderExpectations(kExpectedSession, kExpectedCredentials, - std::string(), kClientStr, std::string(), - std::string(), std::string(), - std::vector<std::string>(), &expected_header); - } else { - SetHeaderExpectations(kExpectedSession, kExpectedCredentials, - std::string(), kClientStr, std::string(), - std::string(), "low", std::vector<std::string>(), - &expected_header); - } - - if (tests[i].slow_connections_flag_enabled) { - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kDataReductionProxyLoFi, - switches::kDataReductionProxyLoFiValueSlowConnectionsOnly); - } - - base::FieldTrialList field_trial_list(nullptr); - if (tests[i].auto_lofi_enabled_group) { - base::FieldTrialList::CreateFieldTrial(params::GetLoFiFieldTrialName(), - "Enabled"); - } - - test_context_->config()->SetNetworkProhibitivelySlow( - tests[i].network_prohibitively_slow); - - CreateRequest(); - - CreateRequestOptions(kBogusVersion); - VerifyExpectedHeader( - params()->DefaultOrigin(), expected_header, - test_context_->config()->ShouldEnableLoFiMode(request())); - } + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); } TEST_F(DataReductionProxyRequestOptionsTest, SecureSession) { std::string expected_header; SetHeaderExpectations(std::string(), std::string(), kSecureSession, - kClientStr, std::string(), std::string(), std::string(), + kClientStr, std::string(), std::string(), std::vector<std::string>(), &expected_header); CreateRequestOptions(kBogusVersion); request_options()->SetSecureSession(kSecureSession); - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header, false); + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); } TEST_F(DataReductionProxyRequestOptionsTest, ParseExperiments) { @@ -485,11 +299,11 @@ expected_experiments.push_back("\"foo,bar\""); std::string expected_header; SetHeaderExpectations(kExpectedSession, kExpectedCredentials, std::string(), - kClientStr, std::string(), std::string(), std::string(), + kClientStr, std::string(), std::string(), expected_experiments, &expected_header); CreateRequestOptions(kBogusVersion); - VerifyExpectedHeader(params()->DefaultOrigin(), expected_header, false); + VerifyExpectedHeader(params()->DefaultOrigin(), expected_header); } TEST_F(DataReductionProxyRequestOptionsTest, ParseLocalSessionKey) {
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc index 0edb70f..71879e4e 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
@@ -26,6 +26,7 @@ const char kActionValueDelimiter = '='; const char kChromeProxyLoFiDirective[] = "q=low"; +const char kChromeProxyLoFiExperimentDirective[] = "exp=lofi_active_control"; const char kChromeProxyActionBlockOnce[] = "block-once"; const char kChromeProxyActionBlock[] = "block"; @@ -60,6 +61,10 @@ return kChromeProxyLoFiDirective; } +const char* chrome_proxy_lo_fi_experiment_directive() { + return kChromeProxyLoFiExperimentDirective; +} + bool GetDataReductionProxyActionValue( const net::HttpResponseHeaders* headers, const std::string& action_prefix,
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h index 4505d58..49fa569 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
@@ -71,6 +71,10 @@ // and responses. const char* chrome_proxy_lo_fi_directive(); +// Gets the Chrome-Proxy directive used by data reduction proxy Lo-Fi control +// experiment requests. +const char* chrome_proxy_lo_fi_experiment_directive(); + // Returns true if the Chrome-Proxy header is present and contains a bypass // delay. Sets |proxy_info->bypass_duration| to the specified delay if greater // than 0, and to 0 otherwise to indicate that the default proxy delay
diff --git a/components/data_reduction_proxy/core/common/lofi_decider.h b/components/data_reduction_proxy/core/common/lofi_decider.h index dfe484c6..727b87b 100644 --- a/components/data_reduction_proxy/core/common/lofi_decider.h +++ b/components/data_reduction_proxy/core/common/lofi_decider.h
@@ -8,6 +8,10 @@ #include "base/macros.h" #include "net/url_request/url_request.h" +namespace net { +class HttpRequestHeaders; +} + namespace data_reduction_proxy { // Interface to determine if a request should be made for a low fidelity version @@ -17,9 +21,16 @@ virtual ~LoFiDecider() {} // Returns true when Lo-Fi mode is on for the given |request|. This means the - // Lo-Fi header should be added to the given request, unless the user is in - // in the Lo-Fi control group. + // Lo-Fi header should be added to the given request. virtual bool IsUsingLoFiMode(const net::URLRequest& request) const = 0; + + // Returns true when Lo-Fi mode is on for the given |request|. If the + // |request| is using Lo-Fi mode, adds the "q=low" directive to the |headers|. + // If the user is in the experiment control group and Lo-Fi is on, adds the + // experiment directive "exp=lofi_active_control". + virtual bool MaybeAddLoFiDirectiveToHeaders( + const net::URLRequest& request, + net::HttpRequestHeaders* headers) const = 0; }; } // namespace data_reduction_proxy
diff --git a/components/error_page.gypi b/components/error_page.gypi index bc465cc..ab54dbf 100644 --- a/components/error_page.gypi +++ b/components/error_page.gypi
@@ -21,6 +21,7 @@ 'error_page/common/error_page_params.h', 'error_page/common/net_error_info.cc', 'error_page/common/net_error_info.h', + 'error_page/common/offline_page_types.h', ], }, ],
diff --git a/components/error_page/common/BUILD.gn b/components/error_page/common/BUILD.gn index 11f6ee6c9..b5ed80e 100644 --- a/components/error_page/common/BUILD.gn +++ b/components/error_page/common/BUILD.gn
@@ -8,6 +8,7 @@ "error_page_params.h", "net_error_info.cc", "net_error_info.h", + "offline_page_types.h", ] deps = [
diff --git a/components/error_page/common/net_error_info.h b/components/error_page/common/net_error_info.h index 1f637e5..42f528b 100644 --- a/components/error_page/common/net_error_info.h +++ b/components/error_page/common/net_error_info.h
@@ -41,10 +41,13 @@ NETWORK_ERROR_DIAGNOSE_BUTTON_CLICKED = 17, // Diagnose button clicked. - // For the "Show all saved pages". - NETWORK_ERROR_PAGE_SHOW_SAVED_PAGES_BUTTON_SHOWN = 18, - NETWORK_ERROR_PAGE_SHOW_SAVED_PAGES_BUTTON_CLICKED = 19, - NETWORK_ERROR_PAGE_SHOW_SAVED_PAGES_BUTTON_ERROR = 20, + // For the button to show all offline pages. + NETWORK_ERROR_PAGE_SHOW_OFFLINE_PAGES_BUTTON_SHOWN = 18, + NETWORK_ERROR_PAGE_SHOW_OFFLINE_PAGES_BUTTON_CLICKED = 19, + + // For the button to show offline copy. + NETWORK_ERROR_PAGE_SHOW_OFFLINE_COPY_BUTTON_SHOWN = 20, + NETWORK_ERROR_PAGE_SHOW_OFFLINE_COPY_BUTTON_CLICKED = 21, NETWORK_ERROR_PAGE_EVENT_MAX, };
diff --git a/components/error_page/common/offline_page_types.h b/components/error_page/common/offline_page_types.h new file mode 100644 index 0000000..ce027b4 --- /dev/null +++ b/components/error_page/common/offline_page_types.h
@@ -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. + +#ifndef COMPONENTS_ERROR_PAGE_COMMON_OFFLINE_PAGE_TYPES_H_ +#define COMPONENTS_ERROR_PAGE_COMMON_OFFLINE_PAGE_TYPES_H_ + +namespace error_page { + +enum class OfflinePageStatus { + // No offline page exists. + NONE, + // An offline copy of current page exists. + HAS_OFFLINE_PAGE, + // An offline copy of current page does not exist, but the offline copies of + // other pages exist. + HAS_OTHER_OFFLINE_PAGES, + + OFFLINE_PAGE_STATUS_LAST = HAS_OTHER_OFFLINE_PAGES, +}; + +} // namespace error_page + +#endif // COMPONENTS_ERROR_PAGE_COMMON_OFFLINE_PAGE_TYPES_H_
diff --git a/components/error_page/renderer/net_error_helper_core.cc b/components/error_page/renderer/net_error_helper_core.cc index db3f4dcd7..e120307 100644 --- a/components/error_page/renderer/net_error_helper_core.cc +++ b/components/error_page/renderer/net_error_helper_core.cc
@@ -380,7 +380,8 @@ reload_button_in_page(false), show_saved_copy_button_in_page(false), show_cached_copy_button_in_page(false), - show_saved_pages_button_in_page(false), + show_offline_pages_button_in_page(false), + show_offline_copy_button_in_page(false), is_finished_loading(false), auto_reload_triggered(false) {} @@ -415,7 +416,8 @@ bool reload_button_in_page; bool show_saved_copy_button_in_page; bool show_cached_copy_button_in_page; - bool show_saved_pages_button_in_page; + bool show_offline_pages_button_in_page; + bool show_offline_copy_button_in_page; // True if a page has completed loading, at which point it can receive // updates. @@ -470,8 +472,10 @@ online_(true), visible_(is_visible), auto_reload_count_(0), - navigation_from_button_(NO_BUTTON), - has_offline_pages_(false) { +#if defined(OS_ANDROID) + offline_page_status_(OfflinePageStatus::NONE), +#endif // defined(OS_ANDROID) + navigation_from_button_(NO_BUTTON) { } NetErrorHelperCore::~NetErrorHelperCore() { @@ -596,8 +600,11 @@ if (committed_error_page_info_->show_saved_copy_button_in_page) { RecordEvent(NETWORK_ERROR_PAGE_SHOW_SAVED_COPY_BUTTON_SHOWN); } - if (committed_error_page_info_->show_saved_pages_button_in_page) { - RecordEvent(NETWORK_ERROR_PAGE_SHOW_SAVED_PAGES_BUTTON_SHOWN); + if (committed_error_page_info_->show_offline_pages_button_in_page) { + RecordEvent(NETWORK_ERROR_PAGE_SHOW_OFFLINE_PAGES_BUTTON_SHOWN); + } + if (committed_error_page_info_->show_offline_copy_button_in_page) { + RecordEvent(NETWORK_ERROR_PAGE_SHOW_OFFLINE_COPY_BUTTON_SHOWN); } if (committed_error_page_info_->reload_button_in_page && committed_error_page_info_->show_saved_copy_button_in_page) { @@ -653,15 +660,17 @@ bool reload_button_in_page; bool show_saved_copy_button_in_page; bool show_cached_copy_button_in_page; - bool show_saved_pages_button_in_page; + bool show_offline_pages_button_in_page; + bool show_offline_copy_button_in_page; delegate_->GenerateLocalizedErrorPage( error, is_failed_post, false /* No diagnostics dialogs allowed for subframes. */, - false /* No "show saved pages" provided in subframes */, + OfflinePageStatus::NONE /* No offline button provided in subframes */, scoped_ptr<ErrorPageParams>(), &reload_button_in_page, &show_saved_copy_button_in_page, &show_cached_copy_button_in_page, - &show_saved_pages_button_in_page, error_html); + &show_offline_pages_button_in_page, + &show_offline_copy_button_in_page, error_html); } } @@ -697,8 +706,11 @@ navigation_correction_params_.search_url = search_url; } -void NetErrorHelperCore::OnSetHasOfflinePages(bool has_offline_pages) { - has_offline_pages_ = has_offline_pages; +void NetErrorHelperCore::OnSetOfflinePageInfo( + OfflinePageStatus offline_page_status) { +#if defined(OS_ANDROID) + offline_page_status_ = offline_page_status; +#endif // defined(OS_ANDROID) } void NetErrorHelperCore::GetErrorHtmlForMainFrame( @@ -728,12 +740,13 @@ delegate_->GenerateLocalizedErrorPage( error, pending_error_page_info->was_failed_post, can_show_network_diagnostics_dialog_, - has_offline_pages_, + GetOfflinePageStatus(), scoped_ptr<ErrorPageParams>(), &pending_error_page_info->reload_button_in_page, &pending_error_page_info->show_saved_copy_button_in_page, &pending_error_page_info->show_cached_copy_button_in_page, - &pending_error_page_info->show_saved_pages_button_in_page, + &pending_error_page_info->show_offline_pages_button_in_page, + &pending_error_page_info->show_offline_copy_button_in_page, error_html); } @@ -758,7 +771,7 @@ GetUpdatedError(committed_error_page_info_->error), committed_error_page_info_->was_failed_post, can_show_network_diagnostics_dialog_, - has_offline_pages_); + GetOfflinePageStatus()); } void NetErrorHelperCore::OnNavigationCorrectionsFetched( @@ -796,12 +809,13 @@ pending_error_page_info_->error, pending_error_page_info_->was_failed_post, can_show_network_diagnostics_dialog_, - has_offline_pages_, + GetOfflinePageStatus(), params.Pass(), &pending_error_page_info_->reload_button_in_page, &pending_error_page_info_->show_saved_copy_button_in_page, &pending_error_page_info_->show_cached_copy_button_in_page, - &pending_error_page_info_->show_saved_pages_button_in_page, + &pending_error_page_info_->show_offline_pages_button_in_page, + &pending_error_page_info_->show_offline_copy_button_in_page, &error_html); } else { // Since |navigation_correction_params| in |pending_error_page_info_| is @@ -966,10 +980,15 @@ delegate_->DiagnoseError( committed_error_page_info_->error.unreachableURL); return; - case SHOW_SAVED_PAGES_BUTTON: - RecordEvent(NETWORK_ERROR_PAGE_SHOW_SAVED_PAGES_BUTTON_CLICKED); + case SHOW_OFFLINE_PAGES_BUTTON: + RecordEvent(NETWORK_ERROR_PAGE_SHOW_OFFLINE_PAGES_BUTTON_CLICKED); delegate_->ShowOfflinePages(); return; + case SHOW_OFFLINE_COPY_BUTTON: + RecordEvent(NETWORK_ERROR_PAGE_SHOW_OFFLINE_COPY_BUTTON_CLICKED); + delegate_->LoadOfflineCopy( + committed_error_page_info_->error.unreachableURL); + return; case NO_BUTTON: NOTREACHED(); return; @@ -1012,4 +1031,12 @@ request_body); } +OfflinePageStatus NetErrorHelperCore::GetOfflinePageStatus() const { +#if defined(OS_ANDROID) + return offline_page_status_; +#else + return OfflinePageStatus::NONE; +#endif // defined(OS_ANDROID) +} + } // namespace error_page
diff --git a/components/error_page/renderer/net_error_helper_core.h b/components/error_page/renderer/net_error_helper_core.h index d5c8930..0d955513 100644 --- a/components/error_page/renderer/net_error_helper_core.h +++ b/components/error_page/renderer/net_error_helper_core.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "components/error_page/common/net_error_info.h" +#include "components/error_page/common/offline_page_types.h" #include "url/gurl.h" namespace base { @@ -50,7 +51,8 @@ EASTER_EGG, SHOW_CACHED_COPY_BUTTON, // "Google cached copy" button label experiment. DIAGNOSE_ERROR, - SHOW_SAVED_PAGES_BUTTON, + SHOW_OFFLINE_PAGES_BUTTON, // "Offline pages" experiment. + SHOW_OFFLINE_COPY_BUTTON, // "Offline pages" experiment. }; // The Delegate handles all interaction with the RenderView, WebFrame, and @@ -62,12 +64,13 @@ const blink::WebURLError& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - bool has_offline_pages, + OfflinePageStatus offline_page_status, scoped_ptr<ErrorPageParams> params, bool* reload_button_shown, bool* show_saved_copy_button_shown, bool* show_cached_copy_button_shown, - bool* show_saved_pages_button_shown, + bool* show_offline_pages_button_shown, + bool* show_offline_copy_button_shown, std::string* html) const = 0; // Loads the given HTML in the frame for use as an error page. @@ -84,7 +87,7 @@ virtual void UpdateErrorPage(const blink::WebURLError& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - bool has_offline_pages) = 0; + OfflinePageStatus offline_page_status) = 0; // Fetches an error page and calls into OnErrorPageFetched when done. Any // previous fetch must either be canceled or finished before calling. Can't @@ -112,9 +115,14 @@ // Run the platform diagnostics too for the specified URL. virtual void DiagnoseError(const GURL& page_url) = 0; - // Shows the UI for offline pages. + // Shows all the offline pages that were saved in storage. virtual void ShowOfflinePages() = 0; + // Loads the offline copy of the page that was saved in storage. + // Note that this is different from the saved copy in the cache as in + // LoadPageFromCache. + virtual void LoadOfflineCopy(const GURL& page_url) = 0; + protected: virtual ~Delegate() {} }; @@ -178,8 +186,9 @@ const std::string& api_key, const GURL& search_url); - // Notifies by the browser whether an offline page exists. - void OnSetHasOfflinePages(bool has_offline_pages); + // Notifies |this| that information about the presence of an offline version + // of the page has been received. + void OnSetOfflinePageInfo(OfflinePageStatus offline_page_status); // Notifies |this| that the network's online status changed. // Handler for NetworkStateChanged notification from the browser process. If @@ -235,6 +244,8 @@ void AutoReloadTimerFired(); void PauseAutoReloadTimer(); + OfflinePageStatus GetOfflinePageStatus() const; + static bool IsReloadableError(const ErrorPageInfo& info); Delegate* delegate_; @@ -287,14 +298,16 @@ int auto_reload_count_; +#if defined(OS_ANDROID) + // Status of offline pages. This is used to decide if offline related button + // will be shown in certain error page. + OfflinePageStatus offline_page_status_; +#endif // defined(OS_ANDROID) + // This value is set only when a navigation has been initiated from // the error page. It is used to detect when such navigations result // in errors. Button navigation_from_button_; - - // Whether an offline page exists. This is used to decide if "Show saved - // pages" will be provided in certain error page. - bool has_offline_pages_; }; } // namespace error_page
diff --git a/components/error_page/renderer/net_error_helper_core_unittest.cc b/components/error_page/renderer/net_error_helper_core_unittest.cc index fbd6b27..4c834da 100644 --- a/components/error_page/renderer/net_error_helper_core_unittest.cc +++ b/components/error_page/renderer/net_error_helper_core_unittest.cc
@@ -160,7 +160,8 @@ reload_bypassing_cache_count_(0), show_saved_copy_count_(0), diagnose_error_count_(0), - show_saved_pages_count_(0), + show_offline_pages_count_(0), + load_offline_copy_count_(0), enable_page_helper_functions_count_(0), default_url_(GURL(kFailedUrl)), error_url_(GURL(content::kUnreachableWebDataURL)), @@ -218,9 +219,9 @@ return diagnose_error_url_; } - int show_saved_pages_count() const { - return show_saved_pages_count_; - } + int show_offline_pages_count() const { return show_offline_pages_count_; } + + int load_offline_copy_count() const { return load_offline_copy_count_; } const GURL& default_url() const { return default_url_; @@ -244,8 +245,8 @@ return last_can_show_network_diagnostics_dialog_; } - bool last_has_offline_pages() const { - return last_has_offline_pages_; + OfflinePageStatus last_offline_page_status() const { + return last_offline_page_status_; } const ErrorPageParams* last_error_page_params() const { @@ -353,21 +354,23 @@ void GenerateLocalizedErrorPage(const WebURLError& error, bool is_failed_post, bool can_show_network_diagnostics_dialog, - bool has_offline_pages, + OfflinePageStatus offline_page_status, scoped_ptr<ErrorPageParams> params, bool* reload_button_shown, bool* show_saved_copy_button_shown, bool* show_cached_copy_button_shown, - bool* show_saved_pages_button_shown, + bool* show_offline_pages_button_shown, + bool* show_offline_copy_button_shown, std::string* html) const override { last_can_show_network_diagnostics_dialog_ = can_show_network_diagnostics_dialog; - last_has_offline_pages_ = has_offline_pages; + last_offline_page_status_ = offline_page_status; last_error_page_params_.reset(params.release()); *reload_button_shown = false; *show_saved_copy_button_shown = false; *show_cached_copy_button_shown = false; - *show_saved_pages_button_shown = false; + *show_offline_pages_button_shown = false; + *show_offline_copy_button_shown = false; *html = ErrorToString(error, is_failed_post); } @@ -380,13 +383,14 @@ enable_page_helper_functions_count_++; } - void UpdateErrorPage(const WebURLError& error, bool is_failed_post, + void UpdateErrorPage(const WebURLError& error, + bool is_failed_post, bool can_show_network_diagnostics_dialog, - bool has_offline_pages) override { + OfflinePageStatus offline_page_status) override { update_count_++; last_can_show_network_diagnostics_dialog_ = can_show_network_diagnostics_dialog; - last_has_offline_pages_ = has_offline_pages; + last_offline_page_status_ = offline_page_status; last_error_page_params_.reset(nullptr); last_error_html_ = ErrorToString(error, is_failed_post); } @@ -437,8 +441,10 @@ diagnose_error_url_ = page_url; } - void ShowOfflinePages() override { - show_saved_pages_count_++; + void ShowOfflinePages() override { show_offline_pages_count_++; } + + void LoadOfflineCopy(const GURL& page_url) override { + load_offline_copy_count_++; } void SendTrackingRequest(const GURL& tracking_url, @@ -483,7 +489,7 @@ // Values passed in to the last call of GenerateLocalizedErrorPage or // UpdateErrorPage. Mutable because GenerateLocalizedErrorPage is const. mutable bool last_can_show_network_diagnostics_dialog_; - mutable bool last_has_offline_pages_; + mutable OfflinePageStatus last_offline_page_status_; mutable scoped_ptr<ErrorPageParams> last_error_page_params_; int reload_count_; @@ -492,7 +498,8 @@ GURL show_saved_copy_url_; int diagnose_error_count_; GURL diagnose_error_url_; - int show_saved_pages_count_; + int show_offline_pages_count_; + int load_offline_copy_count_; int enable_page_helper_functions_count_; @@ -2574,14 +2581,29 @@ EXPECT_EQ(GURL(kFailedUrl), diagnose_error_url()); } -TEST_F(NetErrorHelperCoreTest, ShowSavedPages) { - core()->OnSetHasOfflinePages(true); +#if defined(OS_ANDROID) +TEST_F(NetErrorHelperCoreTest, ShowOfflinePages) { + core()->OnSetOfflinePageInfo(OfflinePageStatus::HAS_OTHER_OFFLINE_PAGES); DoErrorLoad(net::ERR_INTERNET_DISCONNECTED); - EXPECT_TRUE(last_has_offline_pages()); - EXPECT_EQ(0, show_saved_pages_count()); - core()->ExecuteButtonPress(NetErrorHelperCore::SHOW_SAVED_PAGES_BUTTON); - EXPECT_EQ(1, show_saved_pages_count()); + EXPECT_EQ(OfflinePageStatus::HAS_OTHER_OFFLINE_PAGES, + last_offline_page_status()); + EXPECT_EQ(0, show_offline_pages_count()); + EXPECT_EQ(0, load_offline_copy_count()); + core()->ExecuteButtonPress(NetErrorHelperCore::SHOW_OFFLINE_PAGES_BUTTON); + EXPECT_EQ(1, show_offline_pages_count()); } +TEST_F(NetErrorHelperCoreTest, LoadOfflineCopy) { + core()->OnSetOfflinePageInfo(OfflinePageStatus::HAS_OFFLINE_PAGE); + DoErrorLoad(net::ERR_INTERNET_DISCONNECTED); + EXPECT_EQ(OfflinePageStatus::HAS_OFFLINE_PAGE, last_offline_page_status()); + EXPECT_EQ(0, show_offline_pages_count()); + EXPECT_EQ(0, load_offline_copy_count()); + core()->ExecuteButtonPress(NetErrorHelperCore::SHOW_OFFLINE_COPY_BUTTON); + EXPECT_EQ(0, show_offline_pages_count()); + EXPECT_EQ(1, load_offline_copy_count()); +} +#endif // defined(OS_ANDROID) + } // namespace } // namespace error_page
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc index 2f229ad..87d2fc4 100644 --- a/components/exo/buffer.cc +++ b/components/exo/buffer.cc
@@ -49,32 +49,58 @@ return kGLInternalFormats[static_cast<int>(format)]; } -gpu::gles2::GLES2Interface* GetContextGL() { - ui::ContextFactory* context_factory = - aura::Env::GetInstance()->context_factory(); - return context_factory->SharedMainThreadContextProvider()->ContextGL(); -} - } // namespace //////////////////////////////////////////////////////////////////////////////// -// Buffer, public: +// Buffer::Texture -Buffer::Buffer(scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer, - unsigned texture_target) - : gpu_memory_buffer_(gpu_memory_buffer.Pass()), +// Encapsulates the state and logic needed to bind a buffer to a GLES2 texture. +class Buffer::Texture { + public: + Texture(gfx::GpuMemoryBuffer* gpu_memory_buffer, + cc::ContextProvider* context_provider, + unsigned texture_target); + ~Texture(); + + // Returns true if GLES2 resources for texture have been lost. + bool IsLost(); + + // Binds the content of gpu memory buffer to the texture returned by + // mailbox(). Returns a sync token that can be used to when accessing texture + // from a different context. + gpu::SyncToken BindTexImage(); + + // Releases the content of gpu memory buffer after |sync_token| has passed. + void ReleaseTexImage(const gpu::SyncToken& sync_token); + + // Returns the mailbox for this texture. + gpu::Mailbox mailbox() const { return mailbox_; } + + private: + scoped_refptr<cc::ContextProvider> context_provider_; + const unsigned texture_target_; + const gfx::Size size_; + unsigned image_id_; + unsigned texture_id_; + gpu::Mailbox mailbox_; + + DISALLOW_COPY_AND_ASSIGN(Texture); +}; + +Buffer::Texture::Texture(gfx::GpuMemoryBuffer* gpu_memory_buffer, + cc::ContextProvider* context_provider, + unsigned texture_target) + : context_provider_(context_provider), texture_target_(texture_target), - texture_id_(0), - image_id_(0) { - gpu::gles2::GLES2Interface* gles2 = GetContextGL(); - // Create an image for |gpu_memory_buffer_|. - gfx::Size size = gpu_memory_buffer_->GetSize(); + size_(gpu_memory_buffer->GetSize()), + image_id_(0), + texture_id_(0) { + gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); image_id_ = gles2->CreateImageCHROMIUM( - gpu_memory_buffer_->AsClientBuffer(), size.width(), size.height(), - GLInternalFormat(gpu_memory_buffer_->GetFormat())); - // Create a texture with |texture_target_|. - gles2->ActiveTexture(GL_TEXTURE0); + gpu_memory_buffer->AsClientBuffer(), size_.width(), size_.height(), + GLInternalFormat(gpu_memory_buffer->GetFormat())); gles2->GenTextures(1, &texture_id_); + gles2->ActiveTexture(GL_TEXTURE0); gles2->BindTexture(texture_target_, texture_id_); gles2->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gles2->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -85,54 +111,97 @@ gles2->ProduceTextureCHROMIUM(texture_target_, mailbox_.name); } -Buffer::~Buffer() { - gpu::gles2::GLES2Interface* gles2 = GetContextGL(); - if (texture_id_) - gles2->DeleteTextures(1, &texture_id_); - if (image_id_) - gles2->DestroyImageCHROMIUM(image_id_); +Buffer::Texture::~Texture() { + gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); + gles2->ActiveTexture(GL_TEXTURE0); + gles2->DeleteTextures(1, &texture_id_); + gles2->DestroyImageCHROMIUM(image_id_); } -scoped_ptr<cc::SingleReleaseCallback> Buffer::AcquireTextureMailbox( - cc::TextureMailbox* texture_mailbox) { - // Buffer can only be used by one client at a time. If texture id is 0, then a - // previous call to AcquireTextureMailbox() is using this buffer and it has - // not been released yet. - if (!texture_id_) { - DLOG(WARNING) << "Client tried to use a buffer that has not been released"; - return nullptr; - } +bool Buffer::Texture::IsLost() { + gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); + return gles2->GetGraphicsResetStatusKHR() != GL_NO_ERROR; +} - // Take ownerhsip of image and texture ids. - unsigned texture_id = 0; - unsigned image_id = 0; - std::swap(texture_id, texture_id_); - DCHECK_NE(image_id_, 0u); - std::swap(image_id, image_id_); - - // Bind texture to |texture_target_|. - gpu::gles2::GLES2Interface* gles2 = GetContextGL(); +gpu::SyncToken Buffer::Texture::BindTexImage() { + gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); gles2->ActiveTexture(GL_TEXTURE0); - gles2->BindTexture(texture_target_, texture_id); - - // Bind the image to texture. - gles2->BindTexImage2DCHROMIUM(texture_target_, image_id); - - // Create a sync token to ensure that the BindTexImage2DCHROMIUM call is - // processed before issuing any commands that will read from texture. + gles2->BindTexture(texture_target_, texture_id_); + gles2->BindTexImage2DCHROMIUM(texture_target_, image_id_); + // Create and return a sync token that can be used to ensure that the + // BindTexImage2DCHROMIUM call is processed before issuing any commands + // that will read from the texture on a different context. uint64 fence_sync = gles2->InsertFenceSyncCHROMIUM(); - gles2->ShallowFlushCHROMIUM(); + gles2->OrderingBarrierCHROMIUM(); gpu::SyncToken sync_token; gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + return sync_token; +} + +void Buffer::Texture::ReleaseTexImage(const gpu::SyncToken& sync_token) { + gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); + if (sync_token.HasData()) + gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); + gles2->ActiveTexture(GL_TEXTURE0); + gles2->BindTexture(texture_target_, texture_id_); + gles2->ReleaseTexImage2DCHROMIUM(texture_target_, image_id_); +} + +//////////////////////////////////////////////////////////////////////////////// +// Buffer, public: + +Buffer::Buffer(scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer, + unsigned texture_target) + : gpu_memory_buffer_(gpu_memory_buffer.Pass()), + texture_target_(texture_target), + use_count_(0) {} + +Buffer::~Buffer() {} + +scoped_ptr<cc::SingleReleaseCallback> Buffer::ProduceTextureMailbox( + cc::TextureMailbox* texture_mailbox) { + DLOG_IF(WARNING, use_count_) + << "Producing a texture mailbox for a buffer that has not been released"; + + // Increment the use count for this buffer. + ++use_count_; + + // Creating a new texture is relatively expensive so we reuse the last + // texture whenever possible. + scoped_ptr<Texture> texture = last_texture_.Pass(); + + // If texture is lost, destroy it to ensure that we create a new one below. + if (texture && texture->IsLost()) + texture.reset(); + + // Create a new texture if one doesn't already exist. The contents of this + // buffer can be bound to the texture using a call to BindTexImage and must + // be released using a matching ReleaseTexImage call before it can be reused + // or destroyed. + if (!texture) { + // Note: This can fail if GPU acceleration has been disabled. + scoped_refptr<cc::ContextProvider> context_provider = + aura::Env::GetInstance() + ->context_factory() + ->SharedMainThreadContextProvider(); + if (!context_provider) { + DLOG(WARNING) << "Failed to acquire a context provider"; + Release(); // Decrements the use count + return nullptr; + } + texture = make_scoped_ptr(new Texture( + gpu_memory_buffer_.get(), context_provider.get(), texture_target_)); + } + + // This binds the latest contents of this buffer to the texture. + gpu::SyncToken sync_token = texture->BindTexImage(); bool is_overlay_candidate = false; *texture_mailbox = - cc::TextureMailbox(mailbox_, sync_token, texture_target_, + cc::TextureMailbox(texture->mailbox(), sync_token, texture_target_, gpu_memory_buffer_->GetSize(), is_overlay_candidate); return cc::SingleReleaseCallback::Create( - base::Bind(&Buffer::Release, AsWeakPtr(), texture_target_, - texture_id, image_id)) - .Pass(); + base::Bind(&Buffer::ReleaseTexture, AsWeakPtr(), base::Passed(&texture))); } gfx::Size Buffer::GetSize() const { @@ -142,8 +211,9 @@ scoped_refptr<base::trace_event::TracedValue> Buffer::AsTracedValue() const { scoped_refptr<base::trace_event::TracedValue> value = new base::trace_event::TracedValue; - value->SetInteger("width", GetSize().width()); - value->SetInteger("height", GetSize().height()); + gfx::Size size = gpu_memory_buffer_->GetSize(); + value->SetInteger("width", size.width()); + value->SetInteger("height", size.height()); value->SetInteger("format", static_cast<int>(gpu_memory_buffer_->GetFormat())); return value; @@ -152,36 +222,36 @@ //////////////////////////////////////////////////////////////////////////////// // Buffer, private: -// static -void Buffer::Release(base::WeakPtr<Buffer> buffer, - unsigned texture_target, - unsigned texture_id, - unsigned image_id, - const gpu::SyncToken& sync_token, - bool is_lost) { - TRACE_EVENT1("exo", "Buffer::Release", "is_lost", is_lost); - - gpu::gles2::GLES2Interface* gles2 = GetContextGL(); - if (sync_token.HasData()) - gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); - gles2->ActiveTexture(GL_TEXTURE0); - gles2->BindTexture(texture_target, texture_id); - gles2->ReleaseTexImage2DCHROMIUM(texture_target, image_id); - - // Delete resources and return if buffer is gone. - if (!buffer) { - gles2->DeleteTextures(1, &texture_id); - gles2->DestroyImageCHROMIUM(image_id); +void Buffer::Release() { + DCHECK_GT(use_count_, 0u); + if (--use_count_) return; - } - DCHECK_EQ(buffer->texture_id_, 0u); - buffer->texture_id_ = texture_id; - DCHECK_EQ(buffer->image_id_, 0u); - buffer->image_id_ = image_id; + // Run release callback to notify the client that buffer has been released. + if (!release_callback_.is_null()) + release_callback_.Run(); +} - if (!buffer->release_callback_.is_null()) - buffer->release_callback_.Run(); +// static +void Buffer::ReleaseTexture(base::WeakPtr<Buffer> buffer, + scoped_ptr<Texture> texture, + const gpu::SyncToken& sync_token, + bool is_lost) { + TRACE_EVENT1("exo", "Buffer::ReleaseTexture", "is_lost", is_lost); + + // Release image so it can safely be reused or destroyed. + texture->ReleaseTexImage(sync_token); + + // Early out if buffer is gone. This can happen when the client destroyed the + // buffer before receiving a release callback. + if (!buffer) + return; + + // Allow buffer to reused texture if it's not lost. + if (!is_lost) + buffer->last_texture_ = texture.Pass(); + + buffer->Release(); } } // namespace exo
diff --git a/components/exo/buffer.h b/components/exo/buffer.h index 192513b..2f60f5b 100644 --- a/components/exo/buffer.h +++ b/components/exo/buffer.h
@@ -9,9 +9,6 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "gpu/command_buffer/common/mailbox.h" -#include "gpu/command_buffer/common/sync_token.h" -#include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/size.h" namespace base { @@ -29,6 +26,10 @@ class GpuMemoryBuffer; } +namespace gpu { +struct SyncToken; +} + namespace exo { // This class provides the content for a Surface. The mechanism by which a @@ -50,7 +51,7 @@ // This function can be used to acquire a texture mailbox that is bound to // the buffer. Returns a release callback on success. The release callback // must be called before a new texture mailbox can be acquired. - scoped_ptr<cc::SingleReleaseCallback> AcquireTextureMailbox( + scoped_ptr<cc::SingleReleaseCallback> ProduceTextureMailbox( cc::TextureMailbox* mailbox); // Returns the size of the buffer. @@ -60,18 +61,38 @@ scoped_refptr<base::trace_event::TracedValue> AsTracedValue() const; private: - static void Release(base::WeakPtr<Buffer> buffer, - unsigned texture_target, - unsigned texture_id, - unsigned image_id, - const gpu::SyncToken& sync_token, - bool is_lost); + class Texture; + // Decrements the use count of buffer and notifies the client that buffer + // as been released if it reached 0. + void Release(); + + // This is used by ProduceTextureMailbox() to produce a release callback + // that releases the buffer contents referenced by a texture before the + // texture is destroyed or reused. + // Note: This is a static function as it needs to run even if the buffer + // has been destroyed. + static void ReleaseTexture(base::WeakPtr<Buffer> buffer, + scoped_ptr<Texture> texture, + const gpu::SyncToken& sync_token, + bool is_lost); + + // The GPU memory buffer that contains the contents of this buffer. scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; + + // Texture target that must be used when creating a texture for buffer. const unsigned texture_target_; - unsigned texture_id_; - unsigned image_id_; - gpu::Mailbox mailbox_; + + // This is incremented when a texture mailbox is produced and decremented + // when a texture mailbox is released. It is used to determine when we should + // notify the client that buffer has been released. + unsigned use_count_; + + // The last released texture instance. ProduceTextureMailbox() will use this + // instead of creating a new texture when possible. + scoped_ptr<Texture> last_texture_; + + // The client release callback. base::Closure release_callback_; DISALLOW_COPY_AND_ASSIGN(Buffer);
diff --git a/components/exo/buffer_unittest.cc b/components/exo/buffer_unittest.cc index 4da72f4e5..21a2eea 100644 --- a/components/exo/buffer_unittest.cc +++ b/components/exo/buffer_unittest.cc
@@ -2,14 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <GLES2/gl2extchromium.h> + #include "base/bind.h" +#include "cc/output/context_provider.h" #include "cc/resources/single_release_callback.h" #include "components/exo/buffer.h" #include "components/exo/surface.h" #include "components/exo/test/exo_test_base.h" #include "components/exo/test/exo_test_helper.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/khronos/GLES2/gl2.h" +#include "ui/aura/env.h" +#include "ui/compositor/compositor.h" #include "ui/gfx/gpu_memory_buffer.h" namespace exo { @@ -32,15 +38,12 @@ buffer->set_release_callback( base::Bind(&Release, base::Unretained(&release_call_count))); - // Acquire a texture mailbox for the contents of the buffer. + // Produce a texture mailbox for the contents of the buffer. cc::TextureMailbox texture_mailbox; scoped_ptr<cc::SingleReleaseCallback> buffer_release_callback = - buffer->AcquireTextureMailbox(&texture_mailbox); + buffer->ProduceTextureMailbox(&texture_mailbox); ASSERT_TRUE(buffer_release_callback); - // Trying to acquire an already in-use buffer should fail. - EXPECT_FALSE(buffer->AcquireTextureMailbox(&texture_mailbox)); - // Release buffer. buffer_release_callback->Run(gpu::SyncToken(), false); @@ -48,5 +51,39 @@ ASSERT_EQ(release_call_count, 1); } +TEST_F(BufferTest, IsLost) { + gfx::Size buffer_size(256, 256); + scoped_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size).Pass(), + GL_TEXTURE_2D)); + + // Acquire a texture mailbox for the contents of the buffer. + cc::TextureMailbox texture_mailbox; + scoped_ptr<cc::SingleReleaseCallback> buffer_release_callback = + buffer->ProduceTextureMailbox(&texture_mailbox); + ASSERT_TRUE(buffer_release_callback); + + scoped_refptr<cc::ContextProvider> context_provider = + aura::Env::GetInstance() + ->context_factory() + ->SharedMainThreadContextProvider(); + if (context_provider) { + gpu::gles2::GLES2Interface* gles2 = context_provider->ContextGL(); + gles2->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, + GL_INNOCENT_CONTEXT_RESET_ARB); + } + + // Release buffer. + bool is_lost = true; + buffer_release_callback->Run(gpu::SyncToken(), is_lost); + + // Producing a new texture mailbox for the contents of the buffer. + buffer_release_callback = buffer->ProduceTextureMailbox(&texture_mailbox); + ASSERT_TRUE(buffer_release_callback); + + // Release buffer. + buffer_release_callback->Run(gpu::SyncToken(), false); +} + } // namespace } // namespace exo
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 3f062385..83f5972 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -41,8 +41,9 @@ // Surface, public: Surface::Surface() - : needs_commit_surface_hierarchy_(false), - has_contents_(false), + : has_pending_contents_(false), + needs_commit_surface_hierarchy_(false), + update_contents_after_successful_compositing_(false), compositor_(nullptr), delegate_(nullptr) { SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR)); @@ -71,6 +72,7 @@ void Surface::Attach(Buffer* buffer) { TRACE_EVENT1("exo", "Surface::Attach", "buffer", buffer->AsTracedValue()); + has_pending_contents_ = true; pending_buffer_ = buffer ? buffer->AsWeakPtr() : base::WeakPtr<Buffer>(); PreferredSizeChanged(); } @@ -197,34 +199,41 @@ DCHECK(needs_commit_surface_hierarchy_); needs_commit_surface_hierarchy_ = false; - cc::TextureMailbox texture_mailbox; - scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; - if (pending_buffer_) { - texture_mailbox_release_callback = - pending_buffer_->AcquireTextureMailbox(&texture_mailbox); + // We update contents if Attach() has been called since last commit. + if (has_pending_contents_) { + has_pending_contents_ = false; + + current_buffer_ = pending_buffer_; pending_buffer_.reset(); - has_contents_ = true; - } else { - // Show solid color content if there is no pending buffer. - layer()->SetShowSolidColorContent(); - has_contents_ = false; - } - if (texture_mailbox_release_callback) { - // Update layer with the new contents. - layer()->SetTextureMailbox(texture_mailbox, - texture_mailbox_release_callback.Pass(), - texture_mailbox.size_in_pixels()); - layer()->SetTextureFlipped(false); - layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), - texture_mailbox.size_in_pixels())); - layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains( - gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels())))); - } + cc::TextureMailbox texture_mailbox; + scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; + if (current_buffer_) { + texture_mailbox_release_callback = + current_buffer_->ProduceTextureMailbox(&texture_mailbox); + } - // Schedule redraw of the damage region. - layer()->SchedulePaint(pending_damage_); - pending_damage_ = gfx::Rect(); + if (texture_mailbox_release_callback) { + // Update layer with the new contents. + layer()->SetTextureMailbox(texture_mailbox, + texture_mailbox_release_callback.Pass(), + texture_mailbox.size_in_pixels()); + layer()->SetTextureFlipped(false); + layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), + texture_mailbox.size_in_pixels())); + layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains( + gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels())))); + } else { + // Show solid color content if no buffer is attached or we failed + // to produce a texture mailbox for the currently attached buffer. + layer()->SetShowSolidColorContent(); + layer()->SetColor(SK_ColorBLACK); + } + + // Schedule redraw of the damage region. + layer()->SchedulePaint(pending_damage_); + pending_damage_ = gfx::Rect(); + } ui::Compositor* compositor = layer()->GetCompositor(); if (compositor && !pending_frame_callbacks_.empty()) { @@ -322,6 +331,37 @@ } } +void Surface::OnCompositingEnded(ui::Compositor* compositor) { + // Nothing to do in here unless this has been set. + if (!update_contents_after_successful_compositing_) + return; + + update_contents_after_successful_compositing_ = false; + + // Early out if no contents is currently assigned to the surface. + if (!current_buffer_) + return; + + // Update contents by producing a new texture mailbox for the current buffer. + cc::TextureMailbox texture_mailbox; + scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback = + current_buffer_->ProduceTextureMailbox(&texture_mailbox); + if (texture_mailbox_release_callback) { + layer()->SetTextureMailbox(texture_mailbox, + texture_mailbox_release_callback.Pass(), + texture_mailbox.size_in_pixels()); + layer()->SetTextureFlipped(false); + layer()->SchedulePaint(gfx::Rect(texture_mailbox.size_in_pixels())); + } +} + +void Surface::OnCompositingAborted(ui::Compositor* compositor) { + // The contents of this surface might be lost if compositing aborted because + // of a lost graphics context. We recover from this by updating the contents + // of the surface next time the compositor successfully ends compositing. + update_contents_after_successful_compositing_ = true; +} + void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) { compositor->RemoveObserver(this); compositor_ = nullptr;
diff --git a/components/exo/surface.h b/components/exo/surface.h index 0bb6b98..d21b3763 100644 --- a/components/exo/surface.h +++ b/components/exo/surface.h
@@ -98,8 +98,8 @@ void OnCompositingDidCommit(ui::Compositor* compositor) override; void OnCompositingStarted(ui::Compositor* compositor, base::TimeTicks start_time) override; - void OnCompositingEnded(ui::Compositor* compositor) override {} - void OnCompositingAborted(ui::Compositor* compositor) override {} + void OnCompositingEnded(ui::Compositor* compositor) override; + void OnCompositingAborted(ui::Compositor* compositor) override; void OnCompositingLockStateChanged(ui::Compositor* compositor) override {} void OnCompositingShuttingDown(ui::Compositor* compositor) override; @@ -108,7 +108,12 @@ return needs_commit_surface_hierarchy_; } - bool has_contents() const { return has_contents_; } + // This returns true when the surface has some contents assigned to it. + bool has_contents() const { return !!current_buffer_; } + + // This is true when Attach() has been called and new contents should take + // effect next time Commit() is called. + bool has_pending_contents_; // The buffer that will become the content of surface when Commit() is called. base::WeakPtr<Buffer> pending_buffer_; @@ -138,12 +143,16 @@ using SubSurfaceEntryList = std::list<SubSurfaceEntry>; SubSurfaceEntryList pending_sub_surfaces_; + // The buffer that is currently set as content of surface. + base::WeakPtr<Buffer> current_buffer_; + // This is true if a call to Commit() as been made but // CommitSurfaceHierarchy() has not yet been called. bool needs_commit_surface_hierarchy_; - // This is true when surface has some contents assigned to it. - bool has_contents_; + // This is true when the contents of the surface should be updated next time + // the compositor successfully ends compositing. + bool update_contents_after_successful_compositing_; // The compsitor being observer or null if not observing a compositor. ui::Compositor* compositor_;
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc index f867a8d..e38cd6c 100644 --- a/components/exo/surface_unittest.cc +++ b/components/exo/surface_unittest.cc
@@ -32,23 +32,21 @@ buffer->set_release_callback( base::Bind(&ReleaseBuffer, base::Unretained(&release_buffer_call_count))); - scoped_ptr<Surface> surface1(new Surface); - scoped_ptr<Surface> surface2(new Surface); + scoped_ptr<Surface> surface(new Surface); // Attach the buffer to surface1. - surface1->Attach(buffer.get()); - surface1->Commit(); + surface->Attach(buffer.get()); + surface->Commit(); - // Attaching buffer to surface2 when it is already attached to surface1 - // should fail and buffer should remain attached to surface1. - surface2->Attach(buffer.get()); - surface2->Commit(); + // Commit without calling Attach() should have no effect. + surface->Commit(); + EXPECT_EQ(0, release_buffer_call_count); - // Attach a null buffer to surface1, this should release the previously + // Attach a null buffer to surface, this should release the previously // attached buffer. - surface1->Attach(nullptr); - surface1->Commit(); - ASSERT_EQ(release_buffer_call_count, 1); + surface->Attach(nullptr); + surface->Commit(); + ASSERT_EQ(1, release_buffer_call_count); } TEST_F(SurfaceTest, Damage) {
diff --git a/components/flags_ui.gypi b/components/flags_ui.gypi index 3293221..b5292cd 100644 --- a/components/flags_ui.gypi +++ b/components/flags_ui.gypi
@@ -16,20 +16,63 @@ '../base/base.gyp:base_prefs', '../components/components_strings.gyp:components_strings', '../ui/base/ui_base.gyp:ui_base', + 'flags_ui_switches', ], 'sources': [ # Note: sources list duplicated in GN build. 'flags_ui/feature_entry.cc', 'flags_ui/feature_entry.h', 'flags_ui/feature_entry_macros.h', + 'flags_ui/flags_state.cc', + 'flags_ui/flags_state.h', + 'flags_ui/flags_storage.h', 'flags_ui/flags_ui_constants.cc', 'flags_ui/flags_ui_constants.h', 'flags_ui/flags_ui_pref_names.cc', 'flags_ui/flags_ui_pref_names.h', - 'flags_ui/flags_storage.h', 'flags_ui/pref_service_flags_storage.cc', 'flags_ui/pref_service_flags_storage.h', ], }, + { + # GN version: //components/flags_ui:switches + # This is a separate target so that the dependencies of + # //chrome/common can be kept minimal. + 'target_name': 'flags_ui_switches', + 'type': 'static_library', + 'include_dirs': [ + '..', + ], + 'sources': [ + # Note: sources list duplicated in GN build. + 'flags_ui/flags_ui_switches.cc', + 'flags_ui/flags_ui_switches.h', + ], + }, + ], + 'conditions': [ + ['OS=="win" and target_arch=="ia32"', { + 'targets': [ + { + # The flags_ui_switches_win64 target here allows us to use base for + # Win64 targets (the normal build is 32 bits). + 'target_name': 'flags_ui_switches_win64', + 'type': 'static_library', + 'include_dirs': [ + '..', + ], + 'sources': [ + # Note: sources list duplicated in GN build. + 'flags_ui/flags_ui_switches.cc', + 'flags_ui/flags_ui_switches.h', + ], + 'configurations': { + 'Common_Base': { + 'msvs_target_platform': 'x64', + }, + }, + }, + ], + }], ], }
diff --git a/components/flags_ui/BUILD.gn b/components/flags_ui/BUILD.gn index 0678f208..3125261 100644 --- a/components/flags_ui/BUILD.gn +++ b/components/flags_ui/BUILD.gn
@@ -7,6 +7,8 @@ "feature_entry.cc", "feature_entry.h", "feature_entry_macros.h", + "flags_state.cc", + "flags_state.h", "flags_storage.h", "flags_ui_constants.cc", "flags_ui_constants.h", @@ -17,9 +19,36 @@ ] deps = [ + ":switches", "//base", "//base:prefs", "//components/strings", "//ui/base", ] } + +# This is a separate target so that the dependencies of +# //chrome/common can be kept minimal. +source_set("switches") { + sources = [ + "flags_ui_switches.cc", + "flags_ui_switches.h", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "flags_state_unittest.cc", + ] + + deps = [ + ":flags_ui", + ":switches", + "//base", + "//base:prefs", + "//base:prefs_test_support", + "//components/strings", + "//testing/gtest", + ] +}
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc new file mode 100644 index 0000000..b7345b2 --- /dev/null +++ b/components/flags_ui/flags_state.cc
@@ -0,0 +1,632 @@ +// Copyright 2015 The Chromium Authors. 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/flags_ui/flags_state.h" + +#include "base/callback.h" +#include "base/feature_list.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "build/build_config.h" +#include "components/flags_ui/feature_entry.h" +#include "components/flags_ui/flags_storage.h" +#include "components/flags_ui/flags_ui_switches.h" +#include "ui/base/l10n/l10n_util.h" + +namespace flags_ui { + +namespace { + +// Convert switch constants to proper CommandLine::StringType strings. +base::CommandLine::StringType GetSwitchString(const std::string& flag) { + base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM); + cmd_line.AppendSwitch(flag); + DCHECK_EQ(2U, cmd_line.argv().size()); + return cmd_line.argv()[1]; +} + +// Scoops flags from a command line. +// Only switches between --flag-switches-begin and --flag-switches-end are +// compared. The embedder may use |extra_flag_sentinel_begin_flag_name| and +// |extra_sentinel_end_flag_name| to specify other delimiters, if supported. +std::set<base::CommandLine::StringType> ExtractFlagsFromCommandLine( + const base::CommandLine& cmdline, + const char* extra_flag_sentinel_begin_flag_name, + const char* extra_flag_sentinel_end_flag_name) { + DCHECK_EQ(!!extra_flag_sentinel_begin_flag_name, + !!extra_flag_sentinel_end_flag_name); + std::set<base::CommandLine::StringType> flags; + // First do the ones between --flag-switches-begin and --flag-switches-end. + base::CommandLine::StringVector::const_iterator first = + std::find(cmdline.argv().begin(), cmdline.argv().end(), + GetSwitchString(switches::kFlagSwitchesBegin)); + base::CommandLine::StringVector::const_iterator last = + std::find(cmdline.argv().begin(), cmdline.argv().end(), + GetSwitchString(switches::kFlagSwitchesEnd)); + if (first != cmdline.argv().end() && last != cmdline.argv().end()) + flags.insert(first + 1, last); + + // Then add those between the extra sentinels. + if (extra_flag_sentinel_begin_flag_name && + extra_flag_sentinel_end_flag_name) { + first = std::find(cmdline.argv().begin(), cmdline.argv().end(), + GetSwitchString(extra_flag_sentinel_begin_flag_name)); + last = std::find(cmdline.argv().begin(), cmdline.argv().end(), + GetSwitchString(extra_flag_sentinel_end_flag_name)); + if (first != cmdline.argv().end() && last != cmdline.argv().end()) + flags.insert(first + 1, last); + } + return flags; +} + +const struct { + unsigned bit; + const char* const name; +} kBitsToOs[] = { + {kOsMac, "Mac"}, + {kOsWin, "Windows"}, + {kOsLinux, "Linux"}, + {kOsCrOS, "Chrome OS"}, + {kOsAndroid, "Android"}, + {kOsCrOSOwnerOnly, "Chrome OS (owner only)"}, +}; + +// Adds a |StringValue| to |list| for each platform where |bitmask| indicates +// whether the entry is available on that platform. +void AddOsStrings(unsigned bitmask, base::ListValue* list) { + for (size_t i = 0; i < arraysize(kBitsToOs); ++i) { + if (bitmask & kBitsToOs[i].bit) + list->Append(new base::StringValue(kBitsToOs[i].name)); + } +} + +// Adds the internal names for the specified entry to |names|. +void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) { + switch (e.type) { + case FeatureEntry::SINGLE_VALUE: + case FeatureEntry::SINGLE_DISABLE_VALUE: + names->insert(e.internal_name); + break; + case FeatureEntry::MULTI_VALUE: + case FeatureEntry::ENABLE_DISABLE_VALUE: + case FeatureEntry::FEATURE_VALUE: + for (int i = 0; i < e.num_choices; ++i) + names->insert(e.NameForChoice(i)); + break; + } +} + +// Confirms that an entry is valid, used in a DCHECK in +// SanitizeList below. +bool ValidateFeatureEntry(const FeatureEntry& e) { + switch (e.type) { + case FeatureEntry::SINGLE_VALUE: + case FeatureEntry::SINGLE_DISABLE_VALUE: + DCHECK_EQ(0, e.num_choices); + DCHECK(!e.choices); + return true; + case FeatureEntry::MULTI_VALUE: + DCHECK_GT(e.num_choices, 0); + DCHECK(e.choices); + DCHECK(e.choices[0].command_line_switch); + DCHECK_EQ('\0', e.choices[0].command_line_switch[0]); + return true; + case FeatureEntry::ENABLE_DISABLE_VALUE: + DCHECK_EQ(3, e.num_choices); + DCHECK(!e.choices); + DCHECK(e.command_line_switch); + DCHECK(e.command_line_value); + DCHECK(e.disable_command_line_switch); + DCHECK(e.disable_command_line_value); + return true; + case FeatureEntry::FEATURE_VALUE: + DCHECK_EQ(3, e.num_choices); + DCHECK(!e.choices); + DCHECK(e.feature); + return true; + } + NOTREACHED(); + return false; +} + +// Returns true if none of this entry's options have been enabled. +bool IsDefaultValue(const FeatureEntry& entry, + const std::set<std::string>& enabled_entries) { + switch (entry.type) { + case FeatureEntry::SINGLE_VALUE: + case FeatureEntry::SINGLE_DISABLE_VALUE: + return enabled_entries.count(entry.internal_name) == 0; + case FeatureEntry::MULTI_VALUE: + case FeatureEntry::ENABLE_DISABLE_VALUE: + case FeatureEntry::FEATURE_VALUE: + for (int i = 0; i < entry.num_choices; ++i) { + if (enabled_entries.count(entry.NameForChoice(i)) > 0) + return false; + } + return true; + } + NOTREACHED(); + return true; +} + +// Returns the Value representing the choice data in the specified entry. +base::Value* CreateChoiceData(const FeatureEntry& entry, + const std::set<std::string>& enabled_entries) { + DCHECK(entry.type == FeatureEntry::MULTI_VALUE || + entry.type == FeatureEntry::ENABLE_DISABLE_VALUE || + entry.type == FeatureEntry::FEATURE_VALUE); + base::ListValue* result = new base::ListValue; + for (int i = 0; i < entry.num_choices; ++i) { + base::DictionaryValue* value = new base::DictionaryValue; + const std::string name = entry.NameForChoice(i); + value->SetString("internal_name", name); + value->SetString("description", entry.DescriptionForChoice(i)); + value->SetBoolean("selected", enabled_entries.count(name) > 0); + result->Append(value); + } + return result; +} + +} // namespace + +// Keeps track of affected switches for each FeatureEntry, based on which +// choice is selected for it. +struct SwitchEntry { + // Corresponding base::Feature to toggle. + std::string feature_name; + + // If |feature_name| is not empty, the state (enable/disabled) to set. + bool feature_state; + + // The name of the switch to add. + std::string switch_name; + + // If |switch_name| is not empty, the value of the switch to set. + std::string switch_value; + + SwitchEntry() : feature_state(false) {} +}; + +FlagsState::FlagsState(const FeatureEntry* feature_entries, + size_t num_feature_entries) + : feature_entries_(feature_entries), + num_feature_entries_(num_feature_entries), + needs_restart_(false) {} + +FlagsState::~FlagsState() {} + +void FlagsState::ConvertFlagsToSwitches( + FlagsStorage* flags_storage, + base::CommandLine* command_line, + SentinelsMode sentinels, + const char* enable_features_flag_name, + const char* disable_features_flag_name) { + std::set<std::string> enabled_entries; + + GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries); + + std::map<std::string, SwitchEntry> name_to_switch_map; + for (size_t i = 0; i < num_feature_entries_; ++i) { + const FeatureEntry& e = feature_entries_[i]; + switch (e.type) { + case FeatureEntry::SINGLE_VALUE: + case FeatureEntry::SINGLE_DISABLE_VALUE: + AddSwitchMapping(e.internal_name, e.command_line_switch, + e.command_line_value, &name_to_switch_map); + break; + case FeatureEntry::MULTI_VALUE: + for (int j = 0; j < e.num_choices; ++j) { + AddSwitchMapping(e.NameForChoice(j), e.choices[j].command_line_switch, + e.choices[j].command_line_value, + &name_to_switch_map); + } + break; + case FeatureEntry::ENABLE_DISABLE_VALUE: + AddSwitchMapping(e.NameForChoice(0), std::string(), std::string(), + &name_to_switch_map); + AddSwitchMapping(e.NameForChoice(1), e.command_line_switch, + e.command_line_value, &name_to_switch_map); + AddSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch, + e.disable_command_line_value, &name_to_switch_map); + break; + case FeatureEntry::FEATURE_VALUE: + AddFeatureMapping(e.NameForChoice(0), std::string(), false, + &name_to_switch_map); + AddFeatureMapping(e.NameForChoice(1), e.feature->name, true, + &name_to_switch_map); + AddFeatureMapping(e.NameForChoice(2), e.feature->name, false, + &name_to_switch_map); + break; + } + } + + AddSwitchesToCommandLine(enabled_entries, name_to_switch_map, sentinels, + command_line, enable_features_flag_name, + disable_features_flag_name); +} + +bool FlagsState::IsRestartNeededToCommitChanges() { + return needs_restart_; +} + +void FlagsState::SetFeatureEntryEnabled(FlagsStorage* flags_storage, + const std::string& internal_name, + bool enable) { + size_t at_index = internal_name.find(testing::kMultiSeparator); + if (at_index != std::string::npos) { + DCHECK(enable); + // We're being asked to enable a multi-choice entry. Disable the + // currently selected choice. + DCHECK_NE(at_index, 0u); + const std::string entry_name = internal_name.substr(0, at_index); + SetFeatureEntryEnabled(flags_storage, entry_name, false); + + // And enable the new choice, if it is not the default first choice. + if (internal_name != entry_name + "@0") { + std::set<std::string> enabled_entries; + GetSanitizedEnabledFlags(flags_storage, &enabled_entries); + needs_restart_ |= enabled_entries.insert(internal_name).second; + flags_storage->SetFlags(enabled_entries); + } + return; + } + + std::set<std::string> enabled_entries; + GetSanitizedEnabledFlags(flags_storage, &enabled_entries); + + const FeatureEntry* e = nullptr; + for (size_t i = 0; i < num_feature_entries_; ++i) { + if (feature_entries_[i].internal_name == internal_name) { + e = feature_entries_ + i; + break; + } + } + DCHECK(e); + + if (e->type == FeatureEntry::SINGLE_VALUE) { + if (enable) + needs_restart_ |= enabled_entries.insert(internal_name).second; + else + needs_restart_ |= (enabled_entries.erase(internal_name) > 0); + } else if (e->type == FeatureEntry::SINGLE_DISABLE_VALUE) { + if (!enable) + needs_restart_ |= enabled_entries.insert(internal_name).second; + else + needs_restart_ |= (enabled_entries.erase(internal_name) > 0); + } else { + if (enable) { + // Enable the first choice. + needs_restart_ |= enabled_entries.insert(e->NameForChoice(0)).second; + } else { + // Find the currently enabled choice and disable it. + for (int i = 0; i < e->num_choices; ++i) { + std::string choice_name = e->NameForChoice(i); + if (enabled_entries.find(choice_name) != enabled_entries.end()) { + needs_restart_ = true; + enabled_entries.erase(choice_name); + // Continue on just in case there's a bug and more than one + // entry for this choice was enabled. + } + } + } + } + + flags_storage->SetFlags(enabled_entries); +} + +void FlagsState::RemoveFlagsSwitches( + std::map<std::string, base::CommandLine::StringType>* switch_list) { + for (const auto& entry : flags_switches_) + switch_list->erase(entry.first); + + // If feature entries were added to --enable-features= or --disable-features= + // lists, remove them here while preserving existing values. + for (const auto& entry : appended_switches_) { + const auto& switch_name = entry.first; + const auto& switch_added_values = entry.second; + + // The below is either a std::string or a base::string16 based on platform. + const auto& existing_value = (*switch_list)[switch_name]; +#if defined(OS_WIN) + const std::string existing_value_utf8 = base::UTF16ToUTF8(existing_value); +#else + const std::string& existing_value_utf8 = existing_value; +#endif + + std::vector<std::string> features = + base::FeatureList::SplitFeatureListString(existing_value_utf8); + std::vector<std::string> remaining_features; + // For any featrue name in |features| that is not in |switch_added_values| - + // i.e. it wasn't added by about_flags code, add it to |remaining_features|. + for (const std::string& feature : features) { + if (!ContainsKey(switch_added_values, feature)) + remaining_features.push_back(feature); + } + + // Either remove the flag entirely if |remaining_features| is empty, or set + // the new list. + if (remaining_features.empty()) { + switch_list->erase(switch_name); + } else { + std::string switch_value = base::JoinString(remaining_features, ","); +#if defined(OS_WIN) + (*switch_list)[switch_name] = base::UTF8ToUTF16(switch_value); +#else + (*switch_list)[switch_name] = switch_value; +#endif + } + } +} + +void FlagsState::ResetAllFlags(FlagsStorage* flags_storage) { + needs_restart_ = true; + + std::set<std::string> no_entries; + flags_storage->SetFlags(no_entries); +} + +void FlagsState::Reset() { + needs_restart_ = false; + flags_switches_.clear(); + appended_switches_.clear(); +} + +void FlagsState::GetFlagFeatureEntries( + FlagsStorage* flags_storage, + FlagAccess access, + base::ListValue* supported_entries, + base::ListValue* unsupported_entries, + base::Callback<bool(const FeatureEntry&)> skip_feature_entry) { + std::set<std::string> enabled_entries; + GetSanitizedEnabledFlags(flags_storage, &enabled_entries); + + int current_platform = GetCurrentPlatform(); + + for (size_t i = 0; i < num_feature_entries_; ++i) { + const FeatureEntry& entry = feature_entries_[i]; + if (skip_feature_entry.Run(entry)) + continue; + + base::DictionaryValue* data = new base::DictionaryValue(); + data->SetString("internal_name", entry.internal_name); + data->SetString("name", l10n_util::GetStringUTF16(entry.visible_name_id)); + data->SetString("description", + l10n_util::GetStringUTF16(entry.visible_description_id)); + + base::ListValue* supported_platforms = new base::ListValue(); + AddOsStrings(entry.supported_platforms, supported_platforms); + data->Set("supported_platforms", supported_platforms); + // True if the switch is not currently passed. + bool is_default_value = IsDefaultValue(entry, enabled_entries); + data->SetBoolean("is_default", is_default_value); + + switch (entry.type) { + case FeatureEntry::SINGLE_VALUE: + case FeatureEntry::SINGLE_DISABLE_VALUE: + data->SetBoolean( + "enabled", + (!is_default_value && entry.type == FeatureEntry::SINGLE_VALUE) || + (is_default_value && + entry.type == FeatureEntry::SINGLE_DISABLE_VALUE)); + break; + case FeatureEntry::MULTI_VALUE: + case FeatureEntry::ENABLE_DISABLE_VALUE: + case FeatureEntry::FEATURE_VALUE: + data->Set("choices", CreateChoiceData(entry, enabled_entries)); + break; + } + + bool supported = (entry.supported_platforms & current_platform) != 0; +#if defined(OS_CHROMEOS) + if (access == kOwnerAccessToFlags && + (entry.supported_platforms & kOsCrOSOwnerOnly) != 0) { + supported = true; + } +#endif + if (supported) + supported_entries->Append(data); + else + unsupported_entries->Append(data); + } +} + +// static +int FlagsState::GetCurrentPlatform() { +#if defined(OS_MACOSX) + return kOsMac; +#elif defined(OS_WIN) + return kOsWin; +#elif defined(OS_CHROMEOS) // Needs to be before the OS_LINUX check. + return kOsCrOS; +#elif defined(OS_LINUX) || defined(OS_OPENBSD) + return kOsLinux; +#elif defined(OS_ANDROID) + return kOsAndroid; +#else +#error Unknown platform +#endif +} + +// static +bool FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + const base::CommandLine& new_cmdline, + const base::CommandLine& active_cmdline, + std::set<base::CommandLine::StringType>* out_difference, + const char* extra_flag_sentinel_begin_flag_name, + const char* extra_flag_sentinel_end_flag_name) { + std::set<base::CommandLine::StringType> new_flags = + ExtractFlagsFromCommandLine(new_cmdline, + extra_flag_sentinel_begin_flag_name, + extra_flag_sentinel_end_flag_name); + std::set<base::CommandLine::StringType> active_flags = + ExtractFlagsFromCommandLine(active_cmdline, + extra_flag_sentinel_begin_flag_name, + extra_flag_sentinel_end_flag_name); + + bool result = false; + // Needed because std::equal doesn't check if the 2nd set is empty. + if (new_flags.size() == active_flags.size()) { + result = + std::equal(new_flags.begin(), new_flags.end(), active_flags.begin()); + } + + if (out_difference && !result) { + std::set_symmetric_difference( + new_flags.begin(), new_flags.end(), active_flags.begin(), + active_flags.end(), + std::inserter(*out_difference, out_difference->begin())); + } + + return result; +} + +void FlagsState::AddSwitchMapping( + const std::string& key, + const std::string& switch_name, + const std::string& switch_value, + std::map<std::string, SwitchEntry>* name_to_switch_map) { + DCHECK(!ContainsKey(*name_to_switch_map, key)); + + SwitchEntry* entry = &(*name_to_switch_map)[key]; + entry->switch_name = switch_name; + entry->switch_value = switch_value; +} + +void FlagsState::AddFeatureMapping( + const std::string& key, + const std::string& feature_name, + bool feature_state, + std::map<std::string, SwitchEntry>* name_to_switch_map) { + DCHECK(!ContainsKey(*name_to_switch_map, key)); + + SwitchEntry* entry = &(*name_to_switch_map)[key]; + entry->feature_name = feature_name; + entry->feature_state = feature_state; +} + +void FlagsState::AddSwitchesToCommandLine( + const std::set<std::string>& enabled_entries, + const std::map<std::string, SwitchEntry>& name_to_switch_map, + SentinelsMode sentinels, + base::CommandLine* command_line, + const char* enable_features_flag_name, + const char* disable_features_flag_name) { + std::map<std::string, bool> feature_switches; + if (sentinels == kAddSentinels) { + command_line->AppendSwitch(switches::kFlagSwitchesBegin); + flags_switches_[switches::kFlagSwitchesBegin] = std::string(); + } + + for (const std::string& entry_name : enabled_entries) { + const auto& entry_it = name_to_switch_map.find(entry_name); + if (entry_it == name_to_switch_map.end()) { + NOTREACHED(); + continue; + } + + const SwitchEntry& entry = entry_it->second; + if (!entry.feature_name.empty()) { + feature_switches[entry.feature_name] = entry.feature_state; + } else if (!entry.switch_name.empty()) { + command_line->AppendSwitchASCII(entry.switch_name, entry.switch_value); + flags_switches_[entry.switch_name] = entry.switch_value; + } + // If an entry doesn't match either of the above, then it is likely the + // default entry for a FEATURE_VALUE entry. Safe to ignore. + } + + if (!feature_switches.empty()) { + MergeFeatureCommandLineSwitch(feature_switches, enable_features_flag_name, + true, command_line); + MergeFeatureCommandLineSwitch(feature_switches, disable_features_flag_name, + false, command_line); + } + + if (sentinels == kAddSentinels) { + command_line->AppendSwitch(switches::kFlagSwitchesEnd); + flags_switches_[switches::kFlagSwitchesEnd] = std::string(); + } +} + +void FlagsState::MergeFeatureCommandLineSwitch( + const std::map<std::string, bool>& feature_switches, + const char* switch_name, + bool feature_state, + base::CommandLine* command_line) { + std::string original_switch_value = + command_line->GetSwitchValueASCII(switch_name); + std::vector<std::string> features = + base::FeatureList::SplitFeatureListString(original_switch_value); + // Only add features that don't already exist in the lists. + // Note: The ContainsValue() call results in O(n^2) performance, but in + // practice n should be very small. + for (const auto& entry : feature_switches) { + if (entry.second == feature_state && + !ContainsValue(features, entry.first)) { + features.push_back(entry.first); + appended_switches_[switch_name].insert(entry.first); + } + } + // Update the switch value only if it didn't change. This avoids setting an + // empty list or duplicating the same list (since AppendSwitch() adds the + // switch to the end but doesn't remove previous ones). + std::string switch_value = base::JoinString(features, ","); + if (switch_value != original_switch_value) + command_line->AppendSwitchASCII(switch_name, switch_value); +} + +void FlagsState::SanitizeList(FlagsStorage* flags_storage) { + std::set<std::string> known_entries; + for (size_t i = 0; i < num_feature_entries_; ++i) { + DCHECK(ValidateFeatureEntry(feature_entries_[i])); + AddInternalName(feature_entries_[i], &known_entries); + } + + std::set<std::string> enabled_entries = flags_storage->GetFlags(); + + std::set<std::string> new_enabled_entries = + base::STLSetIntersection<std::set<std::string>>(known_entries, + enabled_entries); + + if (new_enabled_entries != enabled_entries) + flags_storage->SetFlags(new_enabled_entries); +} + +void FlagsState::GetSanitizedEnabledFlags(FlagsStorage* flags_storage, + std::set<std::string>* result) { + SanitizeList(flags_storage); + *result = flags_storage->GetFlags(); +} + +void FlagsState::GetSanitizedEnabledFlagsForCurrentPlatform( + FlagsStorage* flags_storage, + std::set<std::string>* result) { + GetSanitizedEnabledFlags(flags_storage, result); + + // Filter out any entries that aren't enabled on the current platform. We + // don't remove these from prefs else syncing to a platform with a different + // set of entries would be lossy. + std::set<std::string> platform_entries; + int current_platform = GetCurrentPlatform(); + for (size_t i = 0; i < num_feature_entries_; ++i) { + const FeatureEntry& entry = feature_entries_[i]; + if (entry.supported_platforms & current_platform) + AddInternalName(entry, &platform_entries); +#if defined(OS_CHROMEOS) + if (feature_entries_[i].supported_platforms & kOsCrOSOwnerOnly) + AddInternalName(entry, &platform_entries); +#endif + } + + std::set<std::string> new_enabled_entries = + base::STLSetIntersection<std::set<std::string>>(platform_entries, + *result); + + result->swap(new_enabled_entries); +} + +} // namespace flags_ui
diff --git a/components/flags_ui/flags_state.h b/components/flags_ui/flags_state.h new file mode 100644 index 0000000..8f2a19ff --- /dev/null +++ b/components/flags_ui/flags_state.h
@@ -0,0 +1,160 @@ +// Copyright 2015 The Chromium Authors. 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_FLAGS_UI_FLAGS_STATE_H_ +#define COMPONENTS_FLAGS_UI_FLAGS_STATE_H_ + +#include <map> +#include <set> +#include <string> + +#include "base/callback_forward.h" +#include "base/command_line.h" +#include "base/macros.h" + +namespace base { +class ListValue; +} + +namespace flags_ui { + +struct FeatureEntry; +class FlagsStorage; +struct SwitchEntry; + +// Enumeration of OSs. +enum { + kOsMac = 1 << 0, + kOsWin = 1 << 1, + kOsLinux = 1 << 2, + kOsCrOS = 1 << 3, + kOsAndroid = 1 << 4, + kOsCrOSOwnerOnly = 1 << 5 +}; + +// A flag controlling the behavior of the |ConvertFlagsToSwitches| function - +// whether it should add the sentinel switches around flags. +enum SentinelsMode { kNoSentinels, kAddSentinels }; + +// Differentiate between generic flags available on a per session base and flags +// that influence the whole machine and can be said by the admin only. This flag +// is relevant for ChromeOS for now only and dictates whether entries marked +// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not. +enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags }; + +// Stores and encapsulates the little state that about:flags has. +class FlagsState { + public: + FlagsState(const FeatureEntry* feature_entries, size_t num_feature_entries); + ~FlagsState(); + + void ConvertFlagsToSwitches(FlagsStorage* flags_storage, + base::CommandLine* command_line, + SentinelsMode sentinels, + const char* enable_features_flag_name, + const char* disable_features_flag_name); + bool IsRestartNeededToCommitChanges(); + void SetFeatureEntryEnabled(FlagsStorage* flags_storage, + const std::string& internal_name, + bool enable); + void RemoveFlagsSwitches( + std::map<std::string, base::CommandLine::StringType>* switch_list); + void ResetAllFlags(FlagsStorage* flags_storage); + void Reset(); + + // Gets the list of feature entries. Entries that are available for the + // current platform are appended to |supported_entries|; all other entries are + // appended to |unsupported_entries|. + void GetFlagFeatureEntries( + FlagsStorage* flags_storage, + FlagAccess access, + base::ListValue* supported_entries, + base::ListValue* unsupported_entries, + base::Callback<bool(const FeatureEntry&)> skip_feature_entry); + + // Returns the value for the current platform. This is one of the values + // defined by the OS enum above. + // This is exposed only for testing. + static int GetCurrentPlatform(); + + // Compares a set of switches of the two provided command line objects and + // returns true if they are the same and false otherwise. + // If |out_difference| is not NULL, it's filled with set_symmetric_difference + // between sets. + // Only switches between --flag-switches-begin and --flag-switches-end are + // compared. The embedder may use |extra_flag_sentinel_begin_flag_name| and + // |extra_sentinel_end_flag_name| to specify other delimiters, if supported. + static bool AreSwitchesIdenticalToCurrentCommandLine( + const base::CommandLine& new_cmdline, + const base::CommandLine& active_cmdline, + std::set<base::CommandLine::StringType>* out_difference, + const char* extra_flag_sentinel_begin_flag_name, + const char* extra_flag_sentinel_end_flag_name); + + private: + // Adds mapping to |name_to_switch_map| to set the given switch name/value. + void AddSwitchMapping(const std::string& key, + const std::string& switch_name, + const std::string& switch_value, + std::map<std::string, SwitchEntry>* name_to_switch_map); + + // Adds mapping to |name_to_switch_map| to toggle base::Feature |feature_name| + // to state |feature_state|. + void AddFeatureMapping( + const std::string& key, + const std::string& feature_name, + bool feature_state, + std::map<std::string, SwitchEntry>* name_to_switch_map); + + // Updates the switches in |command_line| by applying the modifications + // specified in |name_to_switch_map| for each entry in |enabled_entries|. + // |enable_features_flag_name| and |disable_features_flag_name| are switches + // used by the embedder to enable/disable features respectively if supported. + void AddSwitchesToCommandLine( + const std::set<std::string>& enabled_entries, + const std::map<std::string, SwitchEntry>& name_to_switch_map, + SentinelsMode sentinels, + base::CommandLine* command_line, + const char* enable_features_flag_name, + const char* disable_features_flag_name); + + // Updates |command_line| by merging the value of the --enable-features= or + // --disable-features= list (per the |switch_name| param) with corresponding + // entries in |feature_switches| that have value |feature_state|. Keeps track + // of the changes by updating |appended_switches|. + void MergeFeatureCommandLineSwitch( + const std::map<std::string, bool>& feature_switches, + const char* switch_name, + bool feature_state, + base::CommandLine* command_line); + + // Removes all entries from prefs::kEnabledLabsExperiments that are unknown, + // to prevent this list to become very long as entries are added and removed. + void SanitizeList(FlagsStorage* flags_storage); + + void GetSanitizedEnabledFlags(FlagsStorage* flags_storage, + std::set<std::string>* result); + + // Variant of GetSanitizedEnabledFlags that also removes any flags that aren't + // enabled on the current platform. + void GetSanitizedEnabledFlagsForCurrentPlatform( + FlagsStorage* flags_storage, + std::set<std::string>* result); + + const FeatureEntry* feature_entries_; + size_t num_feature_entries_; + + bool needs_restart_; + std::map<std::string, std::string> flags_switches_; + + // Map from switch name to a set of string, that keeps track which strings + // were appended to existing (list value) switches. + std::map<std::string, std::set<std::string>> appended_switches_; + + DISALLOW_COPY_AND_ASSIGN(FlagsState); +}; + +} // namespace flags_ui + +#endif // COMPONENTS_FLAGS_UI_FLAGS_STATE_H_
diff --git a/components/flags_ui/flags_state_unittest.cc b/components/flags_ui/flags_state_unittest.cc new file mode 100644 index 0000000..32fc7640 --- /dev/null +++ b/components/flags_ui/flags_state_unittest.cc
@@ -0,0 +1,695 @@ +// Copyright 2015 The Chromium Authors. 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/flags_ui/flags_state.h" + +#include <map> +#include <set> +#include <string> + +#include "base/bind.h" +#include "base/feature_list.h" +#include "base/format_macros.h" +#include "base/prefs/pref_registry_simple.h" +#include "base/prefs/testing_pref_service.h" +#include "base/stl_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "components/flags_ui/feature_entry.h" +#include "components/flags_ui/flags_ui_pref_names.h" +#include "components/flags_ui/flags_ui_switches.h" +#include "components/flags_ui/pref_service_flags_storage.h" +#include "grit/components_strings.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace flags_ui { + +namespace { + +const char kFlags1[] = "flag1"; +const char kFlags2[] = "flag2"; +const char kFlags3[] = "flag3"; +const char kFlags4[] = "flag4"; +const char kFlags5[] = "flag5"; +const char kFlags6[] = "flag6"; +const char kFlags7[] = "flag7"; + +const char kSwitch1[] = "switch"; +const char kSwitch2[] = "switch2"; +const char kSwitch3[] = "switch3"; +const char kSwitch6[] = "switch6"; +const char kValueForSwitch2[] = "value_for_switch2"; + +const char kMultiSwitch1[] = "multi_switch1"; +const char kMultiSwitch2[] = "multi_switch2"; +const char kValueForMultiSwitch2[] = "value_for_multi_switch2"; + +const char kEnableDisableValue1[] = "value1"; +const char kEnableDisableValue2[] = "value2"; + +const char kEnableFeatures[] = "dummy-enable-features"; +const char kDisableFeatures[] = "dummy-disable-features"; + +// Those have to be valid ids for the translation system but the value are +// never used, so pick one at random from the current component. +const int kDummyNameId = IDS_FLAGS_UI_WARNING_HEADER; +const int kDummyDescriptionId = IDS_FLAGS_UI_WARNING_TEXT; + +bool SkipFeatureEntry(const FeatureEntry& feature_entry) { + return false; +} + +} // namespace + +const FeatureEntry::Choice kMultiChoices[] = { + {kDummyDescriptionId, "", ""}, + {kDummyDescriptionId, kMultiSwitch1, ""}, + {kDummyDescriptionId, kMultiSwitch2, kValueForMultiSwitch2}, +}; + +const base::Feature kTestFeature{"FeatureName", + base::FEATURE_ENABLED_BY_DEFAULT}; + +// The entries that are set for these tests. The 3rd entry is not supported on +// the current platform, all others are. +static FeatureEntry kEntries[] = { + {kFlags1, kDummyNameId, kDummyDescriptionId, + 0, // Ends up being mapped to the current platform. + FeatureEntry::SINGLE_VALUE, kSwitch1, "", nullptr, nullptr, nullptr, + nullptr, 0}, + {kFlags2, kDummyNameId, kDummyDescriptionId, + 0, // Ends up being mapped to the current platform. + FeatureEntry::SINGLE_VALUE, kSwitch2, kValueForSwitch2, nullptr, nullptr, + nullptr, nullptr, 0}, + {kFlags3, kDummyNameId, kDummyDescriptionId, + 0, // This ends up enabling for an OS other than the current. + FeatureEntry::SINGLE_VALUE, kSwitch3, "", nullptr, nullptr, nullptr, + nullptr, 0}, + {kFlags4, kDummyNameId, kDummyDescriptionId, + 0, // Ends up being mapped to the current platform. + FeatureEntry::MULTI_VALUE, "", "", "", "", nullptr, kMultiChoices, + arraysize(kMultiChoices)}, + {kFlags5, kDummyNameId, kDummyDescriptionId, + 0, // Ends up being mapped to the current platform. + FeatureEntry::ENABLE_DISABLE_VALUE, kSwitch1, kEnableDisableValue1, + kSwitch2, kEnableDisableValue2, nullptr, nullptr, 3}, + {kFlags6, kDummyNameId, kDummyDescriptionId, 0, + FeatureEntry::SINGLE_DISABLE_VALUE, kSwitch6, "", nullptr, nullptr, + nullptr, nullptr, 0}, + {kFlags7, kDummyNameId, kDummyDescriptionId, + 0, // Ends up being mapped to the current platform. + FeatureEntry::FEATURE_VALUE, nullptr, nullptr, nullptr, nullptr, + &kTestFeature, nullptr, 3}, +}; + +class FlagsStateTest : public ::testing::Test { + protected: + FlagsStateTest() : flags_storage_(&prefs_) { + prefs_.registry()->RegisterListPref(prefs::kEnabledLabsExperiments); + + for (size_t i = 0; i < arraysize(kEntries); ++i) + kEntries[i].supported_platforms = FlagsState::GetCurrentPlatform(); + + int os_other_than_current = 1; + while (os_other_than_current == FlagsState::GetCurrentPlatform()) + os_other_than_current <<= 1; + kEntries[2].supported_platforms = os_other_than_current; + flags_state_.reset(new FlagsState(kEntries, arraysize(kEntries))); + } + + TestingPrefServiceSimple prefs_; + PrefServiceFlagsStorage flags_storage_; + scoped_ptr<FlagsState> flags_state_; +}; + +TEST_F(FlagsStateTest, NoChangeNoRestart) { + EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false); + EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); + + // kFlags6 is enabled by default, so enabling should not require a restart. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, true); + EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); +} + +TEST_F(FlagsStateTest, ChangeNeedsRestart) { + EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges()); +} + +// Tests that disabling a default enabled entry requires a restart. +TEST_F(FlagsStateTest, DisableChangeNeedsRestart) { + EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, false); + EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges()); +} + +TEST_F(FlagsStateTest, MultiFlagChangeNeedsRestart) { + const FeatureEntry& entry = kEntries[3]; + ASSERT_EQ(kFlags4, entry.internal_name); + EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); + // Enable the 2nd choice of the multi-value. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), + true); + EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges()); + flags_state_->Reset(); + EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges()); + // Enable the default choice now. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), + true); + EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges()); +} + +TEST_F(FlagsStateTest, AddTwoFlagsRemoveOne) { + // Add two entries, check they're there. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); + + const base::ListValue* entries_list = + prefs_.GetList(prefs::kEnabledLabsExperiments); + ASSERT_TRUE(entries_list != nullptr); + + ASSERT_EQ(2u, entries_list->GetSize()); + + std::string s0; + ASSERT_TRUE(entries_list->GetString(0, &s0)); + std::string s1; + ASSERT_TRUE(entries_list->GetString(1, &s1)); + + EXPECT_TRUE(s0 == kFlags1 || s1 == kFlags1); + EXPECT_TRUE(s0 == kFlags2 || s1 == kFlags2); + + // Remove one entry, check the other's still around. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, false); + + entries_list = prefs_.GetList(prefs::kEnabledLabsExperiments); + ASSERT_TRUE(entries_list != nullptr); + ASSERT_EQ(1u, entries_list->GetSize()); + ASSERT_TRUE(entries_list->GetString(0, &s0)); + EXPECT_TRUE(s0 == kFlags1); +} + +TEST_F(FlagsStateTest, AddTwoFlagsRemoveBoth) { + // Add two entries, check the pref exists. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); + const base::ListValue* entries_list = + prefs_.GetList(prefs::kEnabledLabsExperiments); + ASSERT_TRUE(entries_list != nullptr); + + // Remove both, the pref should have been removed completely. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, false); + entries_list = prefs_.GetList(prefs::kEnabledLabsExperiments); + EXPECT_TRUE(entries_list == nullptr || entries_list->GetSize() == 0); +} + +TEST_F(FlagsStateTest, ConvertFlagsToSwitches) { + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + command_line.AppendSwitch("foo"); + + EXPECT_TRUE(command_line.HasSwitch("foo")); + EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); + + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + + EXPECT_TRUE(command_line.HasSwitch("foo")); + EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); + EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesBegin)); + EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesEnd)); + + base::CommandLine command_line2(base::CommandLine::NO_PROGRAM); + + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line2, + kNoSentinels, kEnableFeatures, + kDisableFeatures); + + EXPECT_TRUE(command_line2.HasSwitch(kSwitch1)); + EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesBegin)); + EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd)); +} + +base::CommandLine::StringType CreateSwitch(const std::string& value) { +#if defined(OS_WIN) + return base::ASCIIToUTF16(value); +#else + return value; +#endif +} + +TEST_F(FlagsStateTest, CompareSwitchesToCurrentCommandLine) { + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + + const std::string kDoubleDash("--"); + + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + command_line.AppendSwitch("foo"); + + base::CommandLine new_command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &new_command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + + EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + new_command_line, command_line, nullptr, nullptr, nullptr)); + { + std::set<base::CommandLine::StringType> difference; + EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + new_command_line, command_line, &difference, nullptr, nullptr)); + EXPECT_EQ(1U, difference.size()); + EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1))); + } + + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + + EXPECT_TRUE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + new_command_line, command_line, nullptr, nullptr, nullptr)); + { + std::set<base::CommandLine::StringType> difference; + EXPECT_TRUE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + new_command_line, command_line, &difference, nullptr, nullptr)); + EXPECT_TRUE(difference.empty()); + } + + // Now both have flags but different. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); + + base::CommandLine another_command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &another_command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + + EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + new_command_line, another_command_line, nullptr, nullptr, nullptr)); + { + std::set<base::CommandLine::StringType> difference; + EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine( + new_command_line, another_command_line, &difference, nullptr, nullptr)); + EXPECT_EQ(2U, difference.size()); + EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1))); + EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch2 + "=" + + kValueForSwitch2))); + } +} + +TEST_F(FlagsStateTest, RemoveFlagSwitches) { + std::map<std::string, base::CommandLine::StringType> switch_list; + switch_list[kSwitch1] = base::CommandLine::StringType(); + switch_list[switches::kFlagSwitchesBegin] = base::CommandLine::StringType(); + switch_list[switches::kFlagSwitchesEnd] = base::CommandLine::StringType(); + switch_list["foo"] = base::CommandLine::StringType(); + + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + + // This shouldn't do anything before ConvertFlagsToSwitches() wasn't called. + flags_state_->RemoveFlagsSwitches(&switch_list); + ASSERT_EQ(4u, switch_list.size()); + EXPECT_TRUE(ContainsKey(switch_list, kSwitch1)); + EXPECT_TRUE(ContainsKey(switch_list, switches::kFlagSwitchesBegin)); + EXPECT_TRUE(ContainsKey(switch_list, switches::kFlagSwitchesEnd)); + EXPECT_TRUE(ContainsKey(switch_list, "foo")); + + // Call ConvertFlagsToSwitches(), then RemoveFlagsSwitches() again. + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + command_line.AppendSwitch("foo"); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + flags_state_->RemoveFlagsSwitches(&switch_list); + + // Now the about:flags-related switch should have been removed. + ASSERT_EQ(1u, switch_list.size()); + EXPECT_TRUE(ContainsKey(switch_list, "foo")); +} + +TEST_F(FlagsStateTest, RemoveFlagSwitches_Features) { + struct { + int enabled_choice; // 0: default, 1: enabled, 2: disabled. + const char* existing_enable_features; + const char* existing_disable_features; + const char* expected_enable_features; + const char* expected_disable_features; + } cases[] = { + // Default value: Should not affect existing flags. + {0, nullptr, nullptr, nullptr, nullptr}, + {0, "A,B", "C", "A,B", "C"}, + // "Enable" option: should only affect enabled list. + {1, nullptr, nullptr, "FeatureName", nullptr}, + {1, "A,B", "C", "A,B,FeatureName", "C"}, + // "Disable" option: should only affect disabled list. + {2, nullptr, nullptr, nullptr, "FeatureName"}, + {2, "A,B", "C", "A,B", "C,FeatureName"}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf( + "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice, + cases[i].existing_enable_features ? cases[i].existing_enable_features + : "null", + cases[i].existing_disable_features ? cases[i].existing_disable_features + : "null")); + + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + if (cases[i].existing_enable_features) { + command_line.AppendSwitchASCII(kEnableFeatures, + cases[i].existing_enable_features); + } + if (cases[i].existing_disable_features) { + command_line.AppendSwitchASCII(kDisableFeatures, + cases[i].existing_disable_features); + } + + flags_state_->Reset(); + + const std::string entry_name = base::StringPrintf( + "%s%s%d", kFlags7, testing::kMultiSeparator, cases[i].enabled_choice); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry_name, true); + + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + auto switch_list = command_line.GetSwitches(); + EXPECT_EQ(cases[i].expected_enable_features != nullptr, + ContainsKey(switch_list, kEnableFeatures)); + if (cases[i].expected_enable_features) + EXPECT_EQ(CreateSwitch(cases[i].expected_enable_features), + switch_list[kEnableFeatures]); + + EXPECT_EQ(cases[i].expected_disable_features != nullptr, + ContainsKey(switch_list, kDisableFeatures)); + if (cases[i].expected_disable_features) + EXPECT_EQ(CreateSwitch(cases[i].expected_disable_features), + switch_list[kDisableFeatures]); + + // RemoveFlagsSwitches() should result in the original values for these + // switches. + switch_list = command_line.GetSwitches(); + flags_state_->RemoveFlagsSwitches(&switch_list); + EXPECT_EQ(cases[i].existing_enable_features != nullptr, + ContainsKey(switch_list, kEnableFeatures)); + if (cases[i].existing_enable_features) + EXPECT_EQ(CreateSwitch(cases[i].existing_enable_features), + switch_list[kEnableFeatures]); + EXPECT_EQ(cases[i].existing_disable_features != nullptr, + ContainsKey(switch_list, kEnableFeatures)); + if (cases[i].existing_disable_features) + EXPECT_EQ(CreateSwitch(cases[i].existing_disable_features), + switch_list[kDisableFeatures]); + } +} + +// Tests enabling entries that aren't supported on the current platform. +TEST_F(FlagsStateTest, PersistAndPrune) { + // Enable entries 1 and 3. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags3, true); + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kSwitch3)); + + // Convert the flags to switches. Entry 3 shouldn't be among the switches + // as it is not applicable to the current platform. + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kSwitch3)); + + // FeatureEntry 3 should show still be persisted in preferences though. + const base::ListValue* entries_list = + prefs_.GetList(prefs::kEnabledLabsExperiments); + ASSERT_TRUE(entries_list); + EXPECT_EQ(2U, entries_list->GetSize()); + std::string s0; + ASSERT_TRUE(entries_list->GetString(0, &s0)); + EXPECT_EQ(kFlags1, s0); + std::string s1; + ASSERT_TRUE(entries_list->GetString(1, &s1)); + EXPECT_EQ(kFlags3, s1); +} + +// Tests that switches which should have values get them in the command +// line. +TEST_F(FlagsStateTest, CheckValues) { + // Enable entries 1 and 2. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true); + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true); + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kSwitch2)); + + // Convert the flags to switches. + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); + EXPECT_EQ(std::string(), command_line.GetSwitchValueASCII(kSwitch1)); + EXPECT_TRUE(command_line.HasSwitch(kSwitch2)); + EXPECT_EQ(std::string(kValueForSwitch2), + command_line.GetSwitchValueASCII(kSwitch2)); + + // Confirm that there is no '=' in the command line for simple switches. + std::string switch1_with_equals = + std::string("--") + std::string(kSwitch1) + std::string("="); +#if defined(OS_WIN) + EXPECT_EQ(base::string16::npos, command_line.GetCommandLineString().find( + base::ASCIIToUTF16(switch1_with_equals))); +#else + EXPECT_EQ(std::string::npos, + command_line.GetCommandLineString().find(switch1_with_equals)); +#endif + + // And confirm there is a '=' for switches with values. + std::string switch2_with_equals = + std::string("--") + std::string(kSwitch2) + std::string("="); +#if defined(OS_WIN) + EXPECT_NE(base::string16::npos, command_line.GetCommandLineString().find( + base::ASCIIToUTF16(switch2_with_equals))); +#else + EXPECT_NE(std::string::npos, + command_line.GetCommandLineString().find(switch2_with_equals)); +#endif + + // And it should persist. + const base::ListValue* entries_list = + prefs_.GetList(prefs::kEnabledLabsExperiments); + ASSERT_TRUE(entries_list); + EXPECT_EQ(2U, entries_list->GetSize()); + std::string s0; + ASSERT_TRUE(entries_list->GetString(0, &s0)); + EXPECT_EQ(kFlags1, s0); + std::string s1; + ASSERT_TRUE(entries_list->GetString(1, &s1)); + EXPECT_EQ(kFlags2, s1); +} + +// Tests multi-value type entries. +TEST_F(FlagsStateTest, MultiValues) { + const FeatureEntry& entry = kEntries[3]; + ASSERT_EQ(kFlags4, entry.internal_name); + + // Initially, the first "deactivated" option of the multi entry should + // be set. + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2)); + } + + // Enable the 2nd choice of the multi-value. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), + true); + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); + EXPECT_TRUE(command_line.HasSwitch(kMultiSwitch2)); + EXPECT_EQ(std::string(kValueForMultiSwitch2), + command_line.GetSwitchValueASCII(kMultiSwitch2)); + } + + // Disable the multi-value entry. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), + true); + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2)); + } +} + +// Tests that disable flags are added when an entry is disabled. +TEST_F(FlagsStateTest, DisableFlagCommandLine) { + // Nothing selected. + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kSwitch6)); + } + + // Disable the entry 6. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, false); + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_TRUE(command_line.HasSwitch(kSwitch6)); + } + + // Enable entry 6. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, true); + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kSwitch6)); + } +} + +TEST_F(FlagsStateTest, EnableDisableValues) { + const FeatureEntry& entry = kEntries[4]; + ASSERT_EQ(kFlags5, entry.internal_name); + + // Nothing selected. + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kSwitch2)); + } + + // "Enable" option selected. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(1), + true); + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_TRUE(command_line.HasSwitch(kSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kSwitch2)); + EXPECT_EQ(kEnableDisableValue1, command_line.GetSwitchValueASCII(kSwitch1)); + } + + // "Disable" option selected. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(2), + true); + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kSwitch1)); + EXPECT_TRUE(command_line.HasSwitch(kSwitch2)); + EXPECT_EQ(kEnableDisableValue2, command_line.GetSwitchValueASCII(kSwitch2)); + } + + // "Default" option selected, same as nothing selected. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForChoice(0), + true); + { + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1)); + EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2)); + } +} + +TEST_F(FlagsStateTest, FeatureValues) { + const FeatureEntry& entry = kEntries[6]; + ASSERT_EQ(kFlags7, entry.internal_name); + + struct { + int enabled_choice; + const char* existing_enable_features; + const char* existing_disable_features; + const char* expected_enable_features; + const char* expected_disable_features; + } cases[] = { + // Nothing selected. + {-1, nullptr, nullptr, "", ""}, + // "Default" option selected, same as nothing selected. + {0, nullptr, nullptr, "", ""}, + // "Enable" option selected. + {1, nullptr, nullptr, "FeatureName", ""}, + // "Disable" option selected. + {2, nullptr, nullptr, "", "FeatureName"}, + // "Enable" option should get added to the existing list. + {1, "Foo,Bar", nullptr, "Foo,Bar,FeatureName", ""}, + // "Disable" option should get added to the existing list. + {2, nullptr, "Foo,Bar", "", "Foo,Bar,FeatureName"}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + SCOPED_TRACE(base::StringPrintf( + "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice, + cases[i].existing_enable_features ? cases[i].existing_enable_features + : "null", + cases[i].existing_disable_features ? cases[i].existing_disable_features + : "null")); + + if (cases[i].enabled_choice != -1) { + flags_state_->SetFeatureEntryEnabled( + &flags_storage_, entry.NameForChoice(cases[i].enabled_choice), true); + } + + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + if (cases[i].existing_enable_features) { + command_line.AppendSwitchASCII(kEnableFeatures, + cases[i].existing_enable_features); + } + if (cases[i].existing_disable_features) { + command_line.AppendSwitchASCII(kDisableFeatures, + cases[i].existing_disable_features); + } + + flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line, + kAddSentinels, kEnableFeatures, + kDisableFeatures); + EXPECT_EQ(cases[i].expected_enable_features, + command_line.GetSwitchValueASCII(kEnableFeatures)); + EXPECT_EQ(cases[i].expected_disable_features, + command_line.GetSwitchValueASCII(kDisableFeatures)); + } +} + +TEST_F(FlagsStateTest, GetFlagFeatureEntries) { + base::ListValue supported_entries; + base::ListValue unsupported_entries; + flags_state_->GetFlagFeatureEntries(&flags_storage_, kGeneralAccessFlagsOnly, + &supported_entries, &unsupported_entries, + base::Bind(&SkipFeatureEntry)); + // All |kEntries| except for |kFlags3| should be supported. + EXPECT_EQ(6u, supported_entries.GetSize()); + EXPECT_EQ(1u, unsupported_entries.GetSize()); + EXPECT_EQ(arraysize(kEntries), + supported_entries.GetSize() + unsupported_entries.GetSize()); +} + +} // namespace flags_ui
diff --git a/components/flags_ui/flags_ui_switches.cc b/components/flags_ui/flags_ui_switches.cc new file mode 100644 index 0000000..79cc2ae --- /dev/null +++ b/components/flags_ui/flags_ui_switches.cc
@@ -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. + +#include "components/flags_ui/flags_ui_switches.h" + +namespace switches { + +// These two flags are added around the switches about:flags adds to the +// command line. This is useful to see which switches were added by about:flags +// on about:version. They don't have any effect. +const char kFlagSwitchesBegin[] = "flag-switches-begin"; +const char kFlagSwitchesEnd[] = "flag-switches-end"; + +} // namespace switches
diff --git a/components/flags_ui/flags_ui_switches.h b/components/flags_ui/flags_ui_switches.h new file mode 100644 index 0000000..a36d28c --- /dev/null +++ b/components/flags_ui/flags_ui_switches.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_FLAGS_UI_FLAGS_UI_SWITCHES_H_ +#define COMPONENTS_FLAGS_UI_FLAGS_UI_SWITCHES_H_ + +namespace switches { + +extern const char kFlagSwitchesBegin[]; +extern const char kFlagSwitchesEnd[]; + +} // namespace switches + +#endif // COMPONENTS_FLAGS_UI_FLAGS_UI_SWITCHES_H_
diff --git a/components/flags_ui_strings.grdp b/components/flags_ui_strings.grdp index 3453b02..0266498f 100644 --- a/components/flags_ui_strings.grdp +++ b/components/flags_ui_strings.grdp
@@ -18,7 +18,7 @@ <message name="IDS_FLAGS_UI_PROMOTE_DEV_CHANNEL" desc="Shown on the about:flags page when we want to promote the Chrome developer channel"> Interested in cool new Chrome features? Try our dev channel at chrome.com/dev. </message> - <message name="IDS_FLAGS_UI_DISABLE" desc="The link for disabling a labs experiment."> + <message name="IDS_FLAGS_UI_DISABLE" desc="The link for disabling a labs experiment."> Disable </message> <message name="IDS_FLAGS_UI_ENABLE" desc="The link for enabling a labs experiment.">
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index ea8b7ec1..a87cc4c1 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -296,7 +296,7 @@ // HistoryBackend::GetVisibleVisitCountToHost. struct VisibleVisitCountToHostResult { // Indicates whether the call to HistoryBackend::GetVisibleVisitCountToHost - // was successfull or not. If false, then both |count| and |first_visit| are + // was successful or not. If false, then both |count| and |first_visit| are // undefined. bool success; int count;
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn index 447d0a22..4e41104 100644 --- a/components/html_viewer/BUILD.gn +++ b/components/html_viewer/BUILD.gn
@@ -9,7 +9,7 @@ import("//tools/grit/repack.gni") if (is_android) { - import("//build/config/android/internal_rules.gni") + import("//build/config/android/rules.gni") import("//mojo/generate_mojo_shell_assets_list.gni") } @@ -291,27 +291,15 @@ } if (is_android) { - html_viewer_unittests_assets = "$root_build_dir/html_viewer_unittests_assets" - - copy_ex("copy_unittest_assets") { - clear_dir = true - deps = [ - ":pak", - "//gin", - ] - dest = html_viewer_unittests_assets + android_assets("unittest_assets") { sources = [ "$root_build_dir/html_viewer.pak", ] - renaming_sources = v8_external_startup_data_renaming_sources - renaming_destinations = v8_external_startup_data_renaming_destinations - } - - generate_mojo_shell_assets_list("build_unittest_assets") { deps = [ - ":copy_unittest_assets", + ":pak", + "//v8:v8_external_startup_data_assets", ] - dir = html_viewer_unittests_assets + disable_compression = true } } @@ -340,8 +328,8 @@ ] if (is_android) { - deps += [ ":build_unittest_assets" ] - apk_asset_location = html_viewer_unittests_assets + apk_deps = [ ":unittest_assets" ] + write_asset_list = true } configs += [ "//v8:external_startup_data" ]
diff --git a/components/html_viewer/html_frame.cc b/components/html_viewer/html_frame.cc index 7f7af61..c58f5e2 100644 --- a/components/html_viewer/html_frame.cc +++ b/components/html_viewer/html_frame.cc
@@ -43,8 +43,6 @@ #include "mojo/application/public/interfaces/shell.mojom.h" #include "mojo/common/common_type_converters.h" #include "mojo/converters/geometry/geometry_type_converters.h" -#include "mojo/public/cpp/system/data_pipe.h" -#include "skia/ext/refptr.h" #include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" @@ -62,9 +60,6 @@ #include "third_party/WebKit/public/web/WebRemoteFrameClient.h" #include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebView.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" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/size.h" #include "url/gurl.h"
diff --git a/components/mus/BUILD.gn b/components/mus/BUILD.gn index bb2ebe5..e89df7e 100644 --- a/components/mus/BUILD.gn +++ b/components/mus/BUILD.gn
@@ -18,11 +18,11 @@ deps = [ ":lib", + "public/interfaces", "//mojo/application/public/cpp:sources", "//mojo/public/cpp/bindings", "//mojo/services/tracing/public/interfaces", "//mojo/shell", - "public/interfaces", ] } } else {
diff --git a/components/mus/example/BUILD.gn b/components/mus/example/BUILD.gn deleted file mode 100644 index 1c6102ec..0000000 --- a/components/mus/example/BUILD.gn +++ /dev/null
@@ -1,39 +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. - -import("//testing/test.gni") - -# Target that builders build. -group("all") { - testonly = true - - deps = [ - ":example", - ":mustash_unittests", - ] -} - -group("example") { - testonly = true - - deps = [ - "//components/mus/example/main", - "//components/mus/example/mock_sysui", - "//components/mus/example/views_examples", - "//components/mus/example/window_type_launcher", - "//mash/wm", - "//mojo/runner", - ] -} - -test("mustash_unittests") { - deps = [ - "//base", - "//base/test:run_all_unittests", - "//base/test:test_config", - "//base/test:test_support", - "//mash/wm:unittests", - "//mojo/platform_handle:platform_handle_impl", - ] -}
diff --git a/components/mus/gles2/gpu_state.cc b/components/mus/gles2/gpu_state.cc index 34481691..f2516bf 100644 --- a/components/mus/gles2/gpu_state.cc +++ b/components/mus/gles2/gpu_state.cc
@@ -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. -// #include "components/mus/gles2/gpu_state.h"
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.cc b/components/mus/public/cpp/lib/window_tree_client_impl.cc index 5ce927fc..e2d26bb 100644 --- a/components/mus/public/cpp/lib/window_tree_client_impl.cc +++ b/components/mus/public/cpp/lib/window_tree_client_impl.cc
@@ -367,15 +367,23 @@ return focused_window_; } -Window* WindowTreeClientImpl::NewWindow() { +Window* WindowTreeClientImpl::NewWindow( + const Window::SharedProperties* properties) { DCHECK(tree_); Window* window = new Window(this, MakeTransportId(connection_id_, next_window_id_++)); + if (properties) + window->properties_ = *properties; AddWindow(window); const uint32_t change_id = ScheduleInFlightChange( make_scoped_ptr(new CrashInFlightChange(window, ChangeType::NEW_WINDOW))); - tree_->NewWindow(change_id, window->id()); + mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties; + if (properties) { + transport_properties = + mojo::Map<mojo::String, mojo::Array<uint8_t>>::From(*properties); + } + tree_->NewWindow(change_id, window->id(), transport_properties.Pass()); return window; }
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.h b/components/mus/public/cpp/lib/window_tree_client_impl.h index f6638ec6..e32451d 100644 --- a/components/mus/public/cpp/lib/window_tree_client_impl.h +++ b/components/mus/public/cpp/lib/window_tree_client_impl.h
@@ -130,7 +130,7 @@ Window* GetRoot() override; Window* GetWindowById(Id id) override; Window* GetFocusedWindow() override; - Window* NewWindow() override; + Window* NewWindow(const Window::SharedProperties* properties) override; bool IsEmbedRoot() override; ConnectionSpecificId GetConnectionId() override;
diff --git a/components/mus/public/cpp/tests/test_window_tree.cc b/components/mus/public/cpp/tests/test_window_tree.cc index 3e89776..a43d358 100644 --- a/components/mus/public/cpp/tests/test_window_tree.cc +++ b/components/mus/public/cpp/tests/test_window_tree.cc
@@ -20,7 +20,10 @@ return true; } -void TestWindowTree::NewWindow(uint32_t change_id, uint32_t window_id) {} +void TestWindowTree::NewWindow( + uint32_t change_id, + uint32_t window_id, + mojo::Map<mojo::String, mojo::Array<uint8_t>> properties) {} void TestWindowTree::DeleteWindow(uint32_t window_id, const DeleteWindowCallback& callback) {}
diff --git a/components/mus/public/cpp/tests/test_window_tree.h b/components/mus/public/cpp/tests/test_window_tree.h index 31a74e3..67521afa 100644 --- a/components/mus/public/cpp/tests/test_window_tree.h +++ b/components/mus/public/cpp/tests/test_window_tree.h
@@ -23,7 +23,10 @@ private: // mojom::WindowTree: - void NewWindow(uint32_t change_id, uint32_t window_id) override; + void NewWindow( + uint32_t change_id, + uint32_t window_id, + mojo::Map<mojo::String, mojo::Array<uint8_t>> properties) override; void DeleteWindow(uint32_t window_id, const DeleteWindowCallback& callback) override; void SetWindowBounds(uint32_t change_id,
diff --git a/components/mus/public/cpp/tests/window_server_test_base.cc b/components/mus/public/cpp/tests/window_server_test_base.cc index 02d9e12..7fc54b5f 100644 --- a/components/mus/public/cpp/tests/window_server_test_base.cc +++ b/components/mus/public/cpp/tests/window_server_test_base.cc
@@ -87,6 +87,7 @@ void WindowServerTestBase::OnEmbed(Window* root) { most_recent_connection_ = root->connection(); EXPECT_TRUE(QuitRunLoop()); + host_->AddActivationParent(root->id()); } void WindowServerTestBase::OnConnectionLost(WindowTreeConnection* connection) {
diff --git a/components/mus/public/cpp/tests/window_server_test_base.h b/components/mus/public/cpp/tests/window_server_test_base.h index 0bb6cda..03d905d 100644 --- a/components/mus/public/cpp/tests/window_server_test_base.h +++ b/components/mus/public/cpp/tests/window_server_test_base.h
@@ -45,6 +45,7 @@ WindowTreeConnection* window_manager() { return window_manager_; } protected: + mojom::WindowTreeHost* host() { return host_.get(); } WindowTreeConnection* most_recent_connection() { return most_recent_connection_; }
diff --git a/components/mus/public/cpp/window_tree_connection.h b/components/mus/public/cpp/window_tree_connection.h index 659dc62c..fc5b7db 100644 --- a/components/mus/public/cpp/window_tree_connection.h +++ b/components/mus/public/cpp/window_tree_connection.h
@@ -5,7 +5,9 @@ #ifndef COMPONENTS_MUS_PUBLIC_CPP_WINDOW_TREE_CONNECTION_H_ #define COMPONENTS_MUS_PUBLIC_CPP_WINDOW_TREE_CONNECTION_H_ +#include <map> #include <string> +#include <vector> #include "components/mus/common/types.h" #include "components/mus/public/interfaces/window_tree.mojom.h" @@ -56,7 +58,9 @@ // Creates and returns a new Window (which is owned by the window server). // Windows are initially hidden, use SetVisible(true) to show. - virtual Window* NewWindow() = 0; + Window* NewWindow() { return NewWindow(nullptr); } + virtual Window* NewWindow( + const std::map<std::string, std::vector<uint8_t>>* properties) = 0; // Returns true if ACCESS_POLICY_EMBED_ROOT was specified. virtual bool IsEmbedRoot() = 0;
diff --git a/components/mus/public/interfaces/window_manager.mojom b/components/mus/public/interfaces/window_manager.mojom index 9c027424..f08a1d0d 100644 --- a/components/mus/public/interfaces/window_manager.mojom +++ b/components/mus/public/interfaces/window_manager.mojom
@@ -16,9 +16,6 @@ // Represents a core interface that should be implemented by any window manager // built on top of Mus. -// For security reasons, methods that take window_ids can only pass window ids -// created by calls to OpenWindow() from the *same connection* to the window -// manager. The callback indicates success or failure. interface WindowManager { // The window's preferred size as defined by its content. Type: gfx::Size. const string kPreferredSize_Property = "prop:preferred-size"; @@ -26,6 +23,8 @@ const string kResizeBehavior_Property = "prop:resize-behavior"; // Bounds the window is restored to. Type: gfx::Rect. const string kRestoreBounds_Property = "prop:restore-bounds"; + // Shadow style for the window. Type mojom::ShadowStyle. + const string kShadowStyle_Property = "prop:shadow-style"; // The window's show state. Type: ShowState. const string kShowState_Property = "prop:show-state"; // The window bounds as set by user input. Type: gfx::Rect.
diff --git a/components/mus/public/interfaces/window_tree.mojom b/components/mus/public/interfaces/window_tree.mojom index 7c57d2f0..f0c619f 100644 --- a/components/mus/public/interfaces/window_tree.mojom +++ b/components/mus/public/interfaces/window_tree.mojom
@@ -86,10 +86,9 @@ // ERROR_CODE_VALUE_IN_USE: a window already exists with the specified id. // ERROR_CODE_ILLEGAL_ARGUMENT: The connection part of |window_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. - NewWindow(uint32 change_id, uint32 window_id); + NewWindow(uint32 change_id, + uint32 window_id, + map<string, array<uint8>>? properties); // Deletes a window. This does not recurse. No hierarchy change notifications // are sent as a result of this. Only the connection that created the window
diff --git a/components/mus/public/interfaces/window_tree_host.mojom b/components/mus/public/interfaces/window_tree_host.mojom index 74109de5..f109d80 100644 --- a/components/mus/public/interfaces/window_tree_host.mojom +++ b/components/mus/public/interfaces/window_tree_host.mojom
@@ -27,6 +27,10 @@ // easily identify the accelerator's action. AddAccelerator(uint32 id, EventMatcher matcher); RemoveAccelerator(uint32 id); + + // Enables (or disables) child windows of |window_id| to be activated. + AddActivationParent(uint32 window_id); + RemoveActivationParent(uint32 window_id); }; interface WindowTreeHostClient {
diff --git a/components/mus/ws/BUILD.gn b/components/mus/ws/BUILD.gn index 63fb2e8..faa1439 100644 --- a/components/mus/ws/BUILD.gn +++ b/components/mus/ws/BUILD.gn
@@ -28,6 +28,7 @@ "focus_controller.cc", "focus_controller.h", "focus_controller_delegate.h", + "focus_controller_observer.h", "forwarding_window_manager.cc", "forwarding_window_manager.h", "operation.cc", @@ -64,7 +65,7 @@ "//cc/surfaces", "//cc/surfaces:surface_id", "//components/mus/common", - "//components/mus/gles2:gles2", + "//components/mus/gles2", "//components/mus/public/interfaces", "//components/mus/surfaces", "//mojo/application/public/cpp", @@ -79,10 +80,10 @@ "//ui/events/platform", "//ui/gfx", "//ui/gfx/geometry", - "//ui/gl:gl", + "//ui/gl", "//ui/mojo/geometry:interfaces", + "//ui/platform_window", "//ui/platform_window:platform_impls", - "//ui/platform_window:platform_window", ] }
diff --git a/components/mus/ws/connection_manager.cc b/components/mus/ws/connection_manager.cc index 4938254..3c8bea5 100644 --- a/components/mus/ws/connection_manager.cc +++ b/components/mus/ws/connection_manager.cc
@@ -58,8 +58,10 @@ delegate_->OnFirstRootConnectionCreated(); } -ServerWindow* ConnectionManager::CreateServerWindow(const WindowId& id) { - ServerWindow* window = new ServerWindow(this, id); +ServerWindow* ConnectionManager::CreateServerWindow( + const WindowId& id, + const std::map<std::string, std::vector<uint8_t>>& properties) { + ServerWindow* window = new ServerWindow(this, id, properties); window->AddObserver(this); return window; }
diff --git a/components/mus/ws/connection_manager.h b/components/mus/ws/connection_manager.h index 967e34b3..c9cd68a 100644 --- a/components/mus/ws/connection_manager.h +++ b/components/mus/ws/connection_manager.h
@@ -7,6 +7,7 @@ #include <map> #include <set> +#include <vector> #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" @@ -14,7 +15,6 @@ #include "components/mus/public/interfaces/window_tree.mojom.h" #include "components/mus/public/interfaces/window_tree_host.mojom.h" #include "components/mus/surfaces/surfaces_state.h" -#include "components/mus/ws/focus_controller_delegate.h" #include "components/mus/ws/ids.h" #include "components/mus/ws/operation.h" #include "components/mus/ws/server_window_delegate.h" @@ -25,7 +25,6 @@ #include "mojo/public/cpp/bindings/binding.h" namespace mus { - namespace ws { class ClientConnection; @@ -48,7 +47,9 @@ // Creates a new ServerWindow. The return value is owned by the caller, but // must be destroyed before ConnectionManager. - ServerWindow* CreateServerWindow(const WindowId& id); + ServerWindow* CreateServerWindow( + const WindowId& id, + const std::map<std::string, std::vector<uint8_t>>& properties); // Returns the id for the next WindowTreeImpl. ConnectionSpecificId GetAndAdvanceNextConnectionId(); @@ -265,7 +266,6 @@ }; } // namespace ws - } // namespace mus #endif // COMPONENTS_MUS_WS_CONNECTION_MANAGER_H_
diff --git a/components/mus/ws/focus_controller.cc b/components/mus/ws/focus_controller.cc index cef209c..91dbb0a 100644 --- a/components/mus/ws/focus_controller.cc +++ b/components/mus/ws/focus_controller.cc
@@ -5,15 +5,15 @@ #include "components/mus/ws/focus_controller.h" #include "components/mus/ws/focus_controller_delegate.h" +#include "components/mus/ws/focus_controller_observer.h" #include "components/mus/ws/server_window.h" #include "components/mus/ws/server_window_drawn_tracker.h" namespace mus { - namespace ws { FocusController::FocusController(FocusControllerDelegate* delegate) - : delegate_(delegate) {} + : delegate_(delegate), focused_window_(nullptr), active_window_(nullptr) {} FocusController::~FocusController() {} @@ -21,11 +21,19 @@ if (GetFocusedWindow() == window) return; - SetFocusedWindowImpl(window, CHANGE_SOURCE_EXPLICIT); + SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); } ServerWindow* FocusController::GetFocusedWindow() { - return drawn_tracker_ ? drawn_tracker_->window() : nullptr; + return focused_window_; +} + +void FocusController::AddObserver(FocusControllerObserver* observer) { + observers_.AddObserver(observer); +} + +void FocusController::RemoveObserver(FocusControllerObserver* observer) { + observers_.RemoveObserver(observer); } bool FocusController::CanBeFocused(ServerWindow* window) const { @@ -38,44 +46,76 @@ } // |window| must be a descendent of an activatable window. - for (ServerWindow* w = window; w; w = w->parent()) { - if (CanBeActivated(w)) - return true; - } - - return false; + return GetActivatableAncestorOf(window) != nullptr; } bool FocusController::CanBeActivated(ServerWindow* window) const { + DCHECK(window); + // The parent window must be allowed to have active children. + if (!delegate_->CanHaveActiveChildren(window->parent())) + return false; + // TODO(sad): Implement this. return true; } -void FocusController::SetFocusedWindowImpl(ServerWindow* window, - ChangeSource change_source) { +ServerWindow* FocusController::GetActivatableAncestorOf( + ServerWindow* window) const { + for (ServerWindow* w = window; w; w = w->parent()) { + if (CanBeActivated(w)) + return w; + } + return nullptr; +} + +void FocusController::SetFocusedWindowImpl( + FocusControllerChangeSource change_source, + ServerWindow* window) { if (window && !CanBeFocused(window)) return; - ServerWindow* old = GetFocusedWindow(); + ServerWindow* old_focused = GetFocusedWindow(); DCHECK(!window || window->IsDrawn()); - // TODO(sad): Activate the closest activatable ancestor window. - if (window) - drawn_tracker_.reset(new ServerWindowDrawnTracker(window, this)); + // Activate the closest activatable ancestor window. + // TODO(sad): The window to activate doesn't necessarily have to be a direct + // ancestor (e.g. could be a transient parent). + ServerWindow* old_active = active_window_; + active_window_ = GetActivatableAncestorOf(window); + if (old_active != active_window_) { + FOR_EACH_OBSERVER(FocusControllerObserver, observers_, + OnActivationChanged(old_active, active_window_)); + } + + FOR_EACH_OBSERVER(FocusControllerObserver, observers_, + OnFocusChanged(change_source, old_focused, window)); + + focused_window_ = window; + // We can currently use only a single ServerWindowDrawnTracker since focused + // window is expected to be a direct descendant of the active window. + if (focused_window_ && active_window_) { + DCHECK(active_window_->Contains(focused_window_)); + } + ServerWindow* track_window = focused_window_; + if (!track_window) + track_window = active_window_; + if (track_window) + drawn_tracker_.reset(new ServerWindowDrawnTracker(track_window, this)); else drawn_tracker_.reset(); - - if (change_source == CHANGE_SOURCE_DRAWN_STATE_CHANGED) - delegate_->OnFocusChanged(old, window); } void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, ServerWindow* window, bool is_drawn) { DCHECK(!is_drawn); // We only observe when drawn. - SetFocusedWindowImpl(ancestor, CHANGE_SOURCE_DRAWN_STATE_CHANGED); + // TODO(sad): If |window| is |focused_window_|, then move focus to the next + // focusable window in |active_window_|, if |active_window_| is still visible. + // If |active_window_| is invisible, or if |window| is |active_window_|, then + // activate the next window that can be activated. + SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED, + ancestor); } } // namespace ws - } // namespace mus
diff --git a/components/mus/ws/focus_controller.h b/components/mus/ws/focus_controller.h index d63f565..0b1894ef 100644 --- a/components/mus/ws/focus_controller.h +++ b/components/mus/ws/focus_controller.h
@@ -6,6 +6,7 @@ #define COMPONENTS_MUS_WS_FOCUS_CONTROLLER_H_ #include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" #include "components/mus/ws/server_window_drawn_tracker_observer.h" namespace mus { @@ -13,11 +14,18 @@ namespace ws { class FocusControllerDelegate; +class FocusControllerObserver; class ServerWindow; class ServerWindowDrawnTracker; -// Tracks a focused window. Focus is moved to another window when the drawn -// state of the focused window changes and the delegate is notified. +// Describes the source of the change. +enum class FocusControllerChangeSource { + EXPLICIT, + DRAWN_STATE_CHANGED, +}; + +// Tracks the focused window. Focus is moved to another window when the drawn +// state of the focused window changes. class FocusController : public ServerWindowDrawnTrackerObserver { public: explicit FocusController(FocusControllerDelegate* delegate); @@ -28,22 +36,21 @@ void SetFocusedWindow(ServerWindow* window); ServerWindow* GetFocusedWindow(); - // Moves activation to the next activatable window. - void CycleActivationForward(); + void AddObserver(FocusControllerObserver* observer); + void RemoveObserver(FocusControllerObserver* observer); private: - // Describes the source of the change. - enum ChangeSource { - CHANGE_SOURCE_EXPLICIT, - CHANGE_SOURCE_DRAWN_STATE_CHANGED, - }; - // Returns whether |window| can be focused or activated. bool CanBeFocused(ServerWindow* window) const; bool CanBeActivated(ServerWindow* window) const; + // Returns the closest activatable ancestor of |window|. Returns nullptr if + // there is no such ancestor. + ServerWindow* GetActivatableAncestorOf(ServerWindow* window) const; + // Implementation of SetFocusedWindow(). - void SetFocusedWindowImpl(ServerWindow* window, ChangeSource change_source); + void SetFocusedWindowImpl(FocusControllerChangeSource change_source, + ServerWindow* window); // ServerWindowDrawnTrackerObserver: void OnDrawnStateChanged(ServerWindow* ancestor, @@ -51,6 +58,13 @@ bool is_drawn) override; FocusControllerDelegate* delegate_; + + ServerWindow* focused_window_; + ServerWindow* active_window_; + + base::ObserverList<FocusControllerObserver> observers_; + + // Keeps track of the visibility of the focused and active window. scoped_ptr<ServerWindowDrawnTracker> drawn_tracker_; DISALLOW_COPY_AND_ASSIGN(FocusController);
diff --git a/components/mus/ws/focus_controller_delegate.h b/components/mus/ws/focus_controller_delegate.h index 11ef9ad..6eca41ca 100644 --- a/components/mus/ws/focus_controller_delegate.h +++ b/components/mus/ws/focus_controller_delegate.h
@@ -13,8 +13,7 @@ class FocusControllerDelegate { public: - virtual void OnFocusChanged(ServerWindow* old_focused_window, - ServerWindow* new_focused_window) = 0; + virtual bool CanHaveActiveChildren(ServerWindow* window) const = 0; protected: ~FocusControllerDelegate() {}
diff --git a/components/mus/ws/focus_controller_observer.h b/components/mus/ws/focus_controller_observer.h new file mode 100644 index 0000000..8edbae1 --- /dev/null +++ b/components/mus/ws/focus_controller_observer.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_MUS_WS_FOCUS_CONTROLLER_OBSERVER_H_ +#define COMPONENTS_MUS_WS_FOCUS_CONTROLLER_OBSERVER_H_ + +namespace mus { +namespace ws { + +enum class FocusControllerChangeSource; +class ServerWindow; + +class FocusControllerObserver { + public: + virtual void OnActivationChanged(ServerWindow* old_active_window, + ServerWindow* new_active_window) = 0; + virtual void OnFocusChanged(FocusControllerChangeSource change_source, + ServerWindow* old_focused_window, + ServerWindow* new_focused_window) = 0; + + protected: + ~FocusControllerObserver() {} +}; + +} // namespace ws +} // namespace mus + +#endif // COMPONENTS_MUS_WS_FOCUS_CONTROLLER_OBSERVER_H_
diff --git a/components/mus/ws/focus_controller_unittest.cc b/components/mus/ws/focus_controller_unittest.cc index 5c97936..fc86877e 100644 --- a/components/mus/ws/focus_controller_unittest.cc +++ b/components/mus/ws/focus_controller_unittest.cc
@@ -5,6 +5,7 @@ #include "components/mus/ws/focus_controller.h" #include "components/mus/ws/focus_controller_delegate.h" +#include "components/mus/ws/focus_controller_observer.h" #include "components/mus/ws/server_window.h" #include "components/mus/ws/test_server_window_delegate.h" #include "testing/gtest/include/gtest/gtest.h" @@ -14,9 +15,10 @@ namespace ws { namespace { -class TestFocusControllerDelegate : public FocusControllerDelegate { +class TestFocusControllerObserver : public FocusControllerObserver, + public FocusControllerDelegate { public: - TestFocusControllerDelegate() + TestFocusControllerObserver() : change_count_(0u), old_focused_window_(nullptr), new_focused_window_(nullptr) {} @@ -32,8 +34,18 @@ private: // FocusControllerDelegate: - void OnFocusChanged(ServerWindow* old_focused_window, + bool CanHaveActiveChildren(ServerWindow* window) const override { + return true; + } + // FocusControllerObserver: + void OnActivationChanged(ServerWindow* old_active_window, + ServerWindow* new_active_window) override {} + void OnFocusChanged(FocusControllerChangeSource source, + ServerWindow* old_focused_window, ServerWindow* new_focused_window) override { + if (source == FocusControllerChangeSource::EXPLICIT) + return; + change_count_++; old_focused_window_ = old_focused_window; new_focused_window_ = new_focused_window; @@ -43,7 +55,7 @@ ServerWindow* old_focused_window_; ServerWindow* new_focused_window_; - DISALLOW_COPY_AND_ASSIGN(TestFocusControllerDelegate); + DISALLOW_COPY_AND_ASSIGN(TestFocusControllerObserver); }; } // namespace @@ -60,50 +72,52 @@ child_child.SetVisible(true); child.Add(&child_child); - TestFocusControllerDelegate focus_delegate; - FocusController focus_controller(&focus_delegate); + TestFocusControllerObserver focus_observer; + FocusController focus_controller(&focus_observer); + focus_controller.AddObserver(&focus_observer); focus_controller.SetFocusedWindow(&child_child); - EXPECT_EQ(0u, focus_delegate.change_count()); + EXPECT_EQ(0u, focus_observer.change_count()); // Remove the ancestor of the focused window, focus should go to the |root|. root.Remove(&child); - EXPECT_EQ(1u, focus_delegate.change_count()); - EXPECT_EQ(&root, focus_delegate.new_focused_window()); - EXPECT_EQ(&child_child, focus_delegate.old_focused_window()); - focus_delegate.ClearAll(); + EXPECT_EQ(1u, focus_observer.change_count()); + EXPECT_EQ(&root, focus_observer.new_focused_window()); + EXPECT_EQ(&child_child, focus_observer.old_focused_window()); + focus_observer.ClearAll(); // Make the focused window invisible. Focus is lost in this case (as no one // to give focus to). root.SetVisible(false); - EXPECT_EQ(1u, focus_delegate.change_count()); - EXPECT_EQ(nullptr, focus_delegate.new_focused_window()); - EXPECT_EQ(&root, focus_delegate.old_focused_window()); - focus_delegate.ClearAll(); + EXPECT_EQ(1u, focus_observer.change_count()); + EXPECT_EQ(nullptr, focus_observer.new_focused_window()); + EXPECT_EQ(&root, focus_observer.old_focused_window()); + focus_observer.ClearAll(); // Go back to initial state and focus |child_child|. root.SetVisible(true); root.Add(&child); focus_controller.SetFocusedWindow(&child_child); - EXPECT_EQ(0u, focus_delegate.change_count()); + EXPECT_EQ(0u, focus_observer.change_count()); // Hide the focused window, focus should go to parent. child_child.SetVisible(false); - EXPECT_EQ(1u, focus_delegate.change_count()); - EXPECT_EQ(&child, focus_delegate.new_focused_window()); - EXPECT_EQ(&child_child, focus_delegate.old_focused_window()); - focus_delegate.ClearAll(); + EXPECT_EQ(1u, focus_observer.change_count()); + EXPECT_EQ(&child, focus_observer.new_focused_window()); + EXPECT_EQ(&child_child, focus_observer.old_focused_window()); + focus_observer.ClearAll(); child_child.SetVisible(true); focus_controller.SetFocusedWindow(&child_child); - EXPECT_EQ(0u, focus_delegate.change_count()); + EXPECT_EQ(0u, focus_observer.change_count()); // Hide the parent of the focused window. child.SetVisible(false); - EXPECT_EQ(1u, focus_delegate.change_count()); - EXPECT_EQ(&root, focus_delegate.new_focused_window()); - EXPECT_EQ(&child_child, focus_delegate.old_focused_window()); - focus_delegate.ClearAll(); + EXPECT_EQ(1u, focus_observer.change_count()); + EXPECT_EQ(&root, focus_observer.new_focused_window()); + EXPECT_EQ(&child_child, focus_observer.old_focused_window()); + focus_observer.ClearAll(); + focus_controller.RemoveObserver(&focus_observer); } } // namespace ws
diff --git a/components/mus/ws/server_window.cc b/components/mus/ws/server_window.cc index 2e40f6f..43fecc60 100644 --- a/components/mus/ws/server_window.cc +++ b/components/mus/ws/server_window.cc
@@ -18,6 +18,11 @@ namespace ws { ServerWindow::ServerWindow(ServerWindowDelegate* delegate, const WindowId& id) + : ServerWindow(delegate, id, Properties()) {} + +ServerWindow::ServerWindow(ServerWindowDelegate* delegate, + const WindowId& id, + const Properties& properties) : delegate_(delegate), id_(id), parent_(nullptr), @@ -26,6 +31,7 @@ visible_(false), opacity_(1), can_focus_(true), + properties_(properties), // Don't notify newly added observers during notification. This causes // problems for code that adds an observer as part of an observer // notification (such as ServerWindowDrawTracker).
diff --git a/components/mus/ws/server_window.h b/components/mus/ws/server_window.h index d12bdfd7..9289125 100644 --- a/components/mus/ws/server_window.h +++ b/components/mus/ws/server_window.h
@@ -40,9 +40,13 @@ // from the parent. class ServerWindow { public: + using Properties = std::map<std::string, std::vector<uint8_t>>; using Windows = std::vector<ServerWindow*>; ServerWindow(ServerWindowDelegate* delegate, const WindowId& id); + ServerWindow(ServerWindowDelegate* delegate, + const WindowId& id, + const Properties& properties); ~ServerWindow(); void AddObserver(ServerWindowObserver* observer); @@ -177,7 +181,7 @@ gfx::Transform transform_; ui::TextInputState text_input_state_; - std::map<std::string, std::vector<uint8_t>> properties_; + Properties properties_; base::ObserverList<ServerWindowObserver> observers_;
diff --git a/components/mus/ws/window_manager_client_apptest.cc b/components/mus/ws/window_manager_client_apptest.cc index 5a2cd989..2587c4b 100644 --- a/components/mus/ws/window_manager_client_apptest.cc +++ b/components/mus/ws/window_manager_client_apptest.cc
@@ -23,6 +23,12 @@ namespace { +int ValidIndexOf(const Window::Children& windows, Window* window) { + Window::Children::const_iterator it = + std::find(windows.begin(), windows.end(), window); + return (it != windows.end()) ? (it - windows.begin()) : -1; +} + class BoundsChangeObserver : public WindowObserver { public: explicit BoundsChangeObserver(Window* window) : window_(window) { @@ -201,6 +207,13 @@ public: WindowServerTest() {} + Window* NewVisibleWindow(Window* parent, WindowTreeConnection* connection) { + Window* window = connection->NewWindow(); + window->SetVisible(true); + parent->AddChild(window); + return window; + } + // Embeds another version of the test app @ window. This runs a run loop until // a response is received, or a timeout. On success the new WindowServer is // returned. @@ -623,6 +636,13 @@ MOJO_DISALLOW_COPY_AND_ASSIGN(FocusChangeObserver); }; +bool WaitForWindowToHaveFocus(Window* window) { + if (window->HasFocus()) + return true; + FocusChangeObserver observer(window); + return WindowServerTestBase::DoRunLoopWithTimeout(); +} + } // namespace TEST_F(WindowServerTest, Focus) { @@ -657,8 +677,7 @@ } { // Add an observer on the Window that loses focus, and make sure the - // observer - // sees the right values. + // observer sees the right values. FocusChangeObserver observer(window11); embedded->GetRoot()->SetFocus(); ASSERT_TRUE(DoRunLoopWithTimeout()); @@ -669,6 +688,64 @@ } } +TEST_F(WindowServerTest, Activation) { + Window* parent = + NewVisibleWindow(window_manager()->GetRoot(), window_manager()); + Window* child1 = NewVisibleWindow(parent, window_manager()); + Window* child2 = NewVisibleWindow(parent, window_manager()); + Window* child3 = NewVisibleWindow(parent, window_manager()); + + child1->AddTransientWindow(child3); + + WindowTreeConnection* embedded1 = Embed(child1).connection; + ASSERT_NE(nullptr, embedded1); + WindowTreeConnection* embedded2 = Embed(child2).connection; + ASSERT_NE(nullptr, embedded2); + + Window* child11 = NewVisibleWindow(embedded1->GetRoot(), embedded1); + Window* child21 = NewVisibleWindow(embedded2->GetRoot(), embedded2); + + WaitForTreeSizeToMatch(parent, 6); + + // Allow the child windows to be activated. + host()->AddActivationParent(parent->id()); + + // |child2| and |child3| are stacked about |child1|. + EXPECT_GT(ValidIndexOf(parent->children(), child2), + ValidIndexOf(parent->children(), child1)); + EXPECT_GT(ValidIndexOf(parent->children(), child3), + ValidIndexOf(parent->children(), child1)); + + // Set focus on |child11|. This should activate |child1|, and raise it over + // |child2|. But |child3| should still be above |child1| because of + // transiency. + child11->SetFocus(); + ASSERT_TRUE(WaitForWindowToHaveFocus(child11)); + ASSERT_TRUE( + WaitForWindowToHaveFocus(window_manager()->GetWindowById(child11->id()))); + EXPECT_EQ(child11->id(), window_manager()->GetFocusedWindow()->id()); + EXPECT_EQ(child11->id(), embedded1->GetFocusedWindow()->id()); + EXPECT_EQ(nullptr, embedded2->GetFocusedWindow()); + EXPECT_GT(ValidIndexOf(parent->children(), child1), + ValidIndexOf(parent->children(), child2)); + EXPECT_GT(ValidIndexOf(parent->children(), child3), + ValidIndexOf(parent->children(), child1)); + + // Set focus on |child21|. This should activate |child2|, and raise it over + // |child1|. + child21->SetFocus(); + ASSERT_TRUE(WaitForWindowToHaveFocus(child21)); + ASSERT_TRUE( + WaitForWindowToHaveFocus(window_manager()->GetWindowById(child21->id()))); + EXPECT_EQ(child21->id(), window_manager()->GetFocusedWindow()->id()); + EXPECT_EQ(child21->id(), embedded2->GetFocusedWindow()->id()); + EXPECT_EQ(nullptr, embedded1->GetFocusedWindow()); + EXPECT_GT(ValidIndexOf(parent->children(), child2), + ValidIndexOf(parent->children(), child1)); + EXPECT_GT(ValidIndexOf(parent->children(), child3), + ValidIndexOf(parent->children(), child1)); +} + namespace { class DestroyedChangedObserver : public WindowObserver {
diff --git a/components/mus/ws/window_tree_apptest.cc b/components/mus/ws/window_tree_apptest.cc index 77755c7..ea44ebc 100644 --- a/components/mus/ws/window_tree_apptest.cc +++ b/components/mus/ws/window_tree_apptest.cc
@@ -241,8 +241,9 @@ // Generally you want NewWindow(), but use this if you need to test given // a complete window id (NewWindow() ors with the connection id). Id NewWindowWithCompleteId(Id id) { + mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->NewWindow(change_id, id); + tree()->NewWindow(change_id, id, properties.Pass()); return WaitForChangeCompleted(change_id) ? id : 0; }
diff --git a/components/mus/ws/window_tree_host_impl.cc b/components/mus/ws/window_tree_host_impl.cc index 6f84e0e7c..35381f2 100644 --- a/components/mus/ws/window_tree_host_impl.cc +++ b/components/mus/ws/window_tree_host_impl.cc
@@ -32,6 +32,7 @@ DisplayManager::Create(app_impl, gpu_state, surfaces_state)), focus_controller_(new FocusController(this)), window_manager_(window_manager.Pass()) { + focus_controller_->AddObserver(this); display_manager_->Init(this); if (client_) { client_.set_connection_error_handler(base::Bind( @@ -40,6 +41,7 @@ } WindowTreeHostImpl::~WindowTreeHostImpl() { + DestroyFocusController(); for (ServerWindow* window : windows_needing_frame_destruction_) window->RemoveObserver(this); } @@ -89,8 +91,6 @@ return; DCHECK(root_window()->Contains(new_focused_window)); focus_controller_->SetFocusedWindow(new_focused_window); - // TODO(beng): have the FocusController notify us via FocusControllerDelegate. - OnFocusChanged(old_focused_window, new_focused_window); } ServerWindow* WindowTreeHostImpl::GetFocusedWindow() { @@ -98,6 +98,10 @@ } void WindowTreeHostImpl::DestroyFocusController() { + if (!focus_controller_) + return; + + focus_controller_->RemoveObserver(this); focus_controller_.reset(); } @@ -133,6 +137,20 @@ event_dispatcher_.RemoveAccelerator(id); } +void WindowTreeHostImpl::AddActivationParent(uint32_t window_id) { + ServerWindow* window = + connection_manager_->GetWindow(WindowIdFromTransportId(window_id)); + if (window) + activation_parents_.insert(window->id()); +} + +void WindowTreeHostImpl::RemoveActivationParent(uint32_t window_id) { + ServerWindow* window = + connection_manager_->GetWindow(WindowIdFromTransportId(window_id)); + if (window) + activation_parents_.erase(window->id()); +} + void WindowTreeHostImpl::OnClientClosed() { // |display_manager_.reset()| destroys the display-manager first, and then // sets |display_manager_| to nullptr. However, destroying |display_manager_| @@ -160,7 +178,8 @@ const mojom::ViewportMetrics& new_metrics) { if (!root_) { root_.reset(connection_manager_->CreateServerWindow( - RootWindowId(connection_manager_->GetAndAdvanceNextHostId()))); + RootWindowId(connection_manager_->GetAndAdvanceNextHostId()), + ServerWindow::Properties())); root_->SetBounds(gfx::Rect(new_metrics.size_in_pixels.To<gfx::Size>())); root_->SetVisible(true); if (delegate_) @@ -185,8 +204,24 @@ } } -void WindowTreeHostImpl::OnFocusChanged(ServerWindow* old_focused_window, - ServerWindow* new_focused_window) { +bool WindowTreeHostImpl::CanHaveActiveChildren(ServerWindow* window) const { + return window && activation_parents_.count(window->id()) > 0; +} + +void WindowTreeHostImpl::OnActivationChanged(ServerWindow* old_active_window, + ServerWindow* new_active_window) { + DCHECK_NE(new_active_window, old_active_window); + if (new_active_window && new_active_window->parent()) { + // Raise the new active window. + // TODO(sad): Let the WM dictate whether to raise the window or not? + new_active_window->parent()->StackChildAtTop(new_active_window); + } +} + +void WindowTreeHostImpl::OnFocusChanged( + FocusControllerChangeSource change_source, + ServerWindow* old_focused_window, + ServerWindow* new_focused_window) { // There are up to four connections that need to be notified: // . the connection containing |old_focused_window|. // . the connection with |old_focused_window| as its root.
diff --git a/components/mus/ws/window_tree_host_impl.h b/components/mus/ws/window_tree_host_impl.h index dd7f0032..4204210 100644 --- a/components/mus/ws/window_tree_host_impl.h +++ b/components/mus/ws/window_tree_host_impl.h
@@ -13,6 +13,7 @@ #include "components/mus/ws/event_dispatcher.h" #include "components/mus/ws/event_dispatcher_delegate.h" #include "components/mus/ws/focus_controller_delegate.h" +#include "components/mus/ws/focus_controller_observer.h" #include "components/mus/ws/server_window.h" #include "components/mus/ws/server_window_observer.h" @@ -31,6 +32,7 @@ // deleted. class WindowTreeHostImpl : public DisplayManagerDelegate, public mojom::WindowTreeHost, + public FocusControllerObserver, public FocusControllerDelegate, public EventDispatcherDelegate, public ServerWindowObserver { @@ -94,6 +96,8 @@ void AddAccelerator(uint32_t id, mojom::EventMatcherPtr event_matcher) override; void RemoveAccelerator(uint32_t id) override; + void AddActivationParent(uint32_t window_id) override; + void RemoveActivationParent(uint32_t window_id) override; private: void OnClientClosed(); @@ -109,7 +113,13 @@ void OnCompositorFrameDrawn() override; // FocusControllerDelegate: - void OnFocusChanged(ServerWindow* old_focused_window, + bool CanHaveActiveChildren(ServerWindow* window) const override; + + // FocusControllerObserver: + void OnActivationChanged(ServerWindow* old_active_window, + ServerWindow* new_active_window) override; + void OnFocusChanged(FocusControllerChangeSource change_source, + ServerWindow* old_focused_window, ServerWindow* new_focused_window) override; // EventDispatcherDelegate: @@ -132,6 +142,8 @@ scoped_ptr<FocusController> focus_controller_; mojom::WindowManagerPtr window_manager_; + std::set<WindowId> activation_parents_; + // Set of windows with surfaces that need to be destroyed once the frame // draws. std::set<ServerWindow*> windows_needing_frame_destruction_;
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc index 88bc7da..3bf09d5 100644 --- a/components/mus/ws/window_tree_impl.cc +++ b/components/mus/ws/window_tree_impl.cc
@@ -119,13 +119,15 @@ change_id, error_code == mojom::WINDOW_MANAGER_ERROR_CODE_SUCCESS); } -bool WindowTreeImpl::NewWindow(const WindowId& window_id) { +bool WindowTreeImpl::NewWindow( + const WindowId& window_id, + const std::map<std::string, std::vector<uint8_t>>& properties) { if (window_id.connection_id != id_) return false; if (window_map_.find(window_id.window_id) != window_map_.end()) return false; window_map_[window_id.window_id] = - connection_manager_->CreateServerWindow(window_id); + connection_manager_->CreateServerWindow(window_id, properties); known_windows_.insert(WindowIdToTransportId(window_id)); return true; } @@ -605,9 +607,18 @@ window->Remove(children[i]); } -void WindowTreeImpl::NewWindow(uint32_t change_id, Id transport_window_id) { +void WindowTreeImpl::NewWindow( + uint32_t change_id, + Id transport_window_id, + mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) { + std::map<std::string, std::vector<uint8_t>> properties; + if (!transport_properties.is_null()) { + properties = + transport_properties.To<std::map<std::string, std::vector<uint8_t>>>(); + } client_->OnChangeCompleted( - change_id, NewWindow(WindowIdFromTransportId(transport_window_id))); + change_id, + NewWindow(WindowIdFromTransportId(transport_window_id), properties)); } void WindowTreeImpl::DeleteWindow(Id transport_window_id,
diff --git a/components/mus/ws/window_tree_impl.h b/components/mus/ws/window_tree_impl.h index 865ae8e..babe1d7c 100644 --- a/components/mus/ws/window_tree_impl.h +++ b/components/mus/ws/window_tree_impl.h
@@ -74,7 +74,8 @@ // These functions are synchronous variants of those defined in the mojom. The // WindowTree implementations all call into these. See the mojom for details. - bool NewWindow(const WindowId& window_id); + bool NewWindow(const WindowId& window_id, + const std::map<std::string, std::vector<uint8_t>>& properties); bool AddWindow(const WindowId& parent_id, const WindowId& child_id); bool AddTransientWindow(const WindowId& window_id, const WindowId& transient_window_id); @@ -190,7 +191,10 @@ mojom::WindowManagerErrorCode error_code); // WindowTree: - void NewWindow(uint32_t change_id, Id transport_window_id) override; + void NewWindow(uint32_t change_id, + Id transport_window_id, + mojo::Map<mojo::String, mojo::Array<uint8_t>> + transport_properties) override; void DeleteWindow(Id transport_window_id, const mojo::Callback<void(bool)>& callback) override; void AddWindow(Id parent_id,
diff --git a/components/mus/ws/window_tree_unittest.cc b/components/mus/ws/window_tree_unittest.cc index 3c13428..d5cffaf 100644 --- a/components/mus/ws/window_tree_unittest.cc +++ b/components/mus/ws/window_tree_unittest.cc
@@ -354,7 +354,8 @@ // Verifies focus correctly changes on pointer events. TEST_F(WindowTreeTest, FocusOnPointer) { const WindowId embed_window_id(wm_connection()->id(), 1); - EXPECT_TRUE(wm_connection()->NewWindow(embed_window_id)); + EXPECT_TRUE( + wm_connection()->NewWindow(embed_window_id, ServerWindow::Properties())); EXPECT_TRUE(wm_connection()->SetWindowVisibility(embed_window_id, true)); EXPECT_TRUE( wm_connection()->AddWindow(*(wm_connection()->root()), embed_window_id)); @@ -379,7 +380,7 @@ ->SetBounds(gfx::Rect(0, 0, 50, 50)); const WindowId child1(connection1->id(), 1); - EXPECT_TRUE(connection1->NewWindow(child1)); + EXPECT_TRUE(connection1->NewWindow(child1, ServerWindow::Properties())); EXPECT_TRUE(connection1->AddWindow(embed_window_id, child1)); ServerWindow* v1 = connection1->GetWindow(child1); v1->SetVisible(true); @@ -389,9 +390,20 @@ connection1_client->tracker()->changes()->clear(); wm_client()->tracker()->changes()->clear(); + // Focus should not go to |child1| yet, since the parent still doesn't allow + // active children. display_manager_delegate()->OnEvent(CreatePointerDownEvent(21, 22)); + EXPECT_EQ(nullptr, connection1->GetHost()->GetFocusedWindow()); + display_manager_delegate()->OnEvent(CreatePointerUpEvent(21, 22)); + connection1_client->tracker()->changes()->clear(); + wm_client()->tracker()->changes()->clear(); + + connection1->GetHost()->AddActivationParent( + WindowIdToTransportId(embed_window_id)); + // Focus should go to child1. This result in notifying both the window // manager and client connection being notified. + display_manager_delegate()->OnEvent(CreatePointerDownEvent(21, 22)); EXPECT_EQ(v1, connection1->GetHost()->GetFocusedWindow()); ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u); EXPECT_EQ("Focused id=2,1", @@ -405,19 +417,10 @@ wm_client()->tracker()->changes()->clear(); connection1_client->tracker()->changes()->clear(); - // Press outside of the embedded window. Focus should go to the root. Notice - // the client1 doesn't see who has focus as the focused window (root) isn't - // visible to it. + // Press outside of the embedded window. Note that root cannot be focused + // (because it cannot be activated). So the focus would not move in this case. display_manager_delegate()->OnEvent(CreatePointerDownEvent(61, 22)); - EXPECT_EQ(host_connection()->window_tree_host()->root_window(), - host_connection()->window_tree_host()->GetFocusedWindow()); - ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u); - EXPECT_EQ("Focused id=0,2", - 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]); + EXPECT_EQ(v1, host_connection()->window_tree_host()->GetFocusedWindow()); display_manager_delegate()->OnEvent(CreatePointerUpEvent(21, 22)); wm_client()->tracker()->changes()->clear(); @@ -426,9 +429,9 @@ // Press in the same location. Should not get a focus change event (only input // event). display_manager_delegate()->OnEvent(CreatePointerDownEvent(61, 22)); - EXPECT_EQ(host_connection()->window_tree_host()->root_window(), - host_connection()->window_tree_host()->GetFocusedWindow()); - ASSERT_EQ(wm_client()->tracker()->changes()->size(), 1u); + EXPECT_EQ(v1, host_connection()->window_tree_host()->GetFocusedWindow()); + ASSERT_EQ(wm_client()->tracker()->changes()->size(), 1u) + << SingleChangeToDescription(*wm_client()->tracker()->changes()); EXPECT_EQ("InputEvent window=0,2 event_action=4", ChangesToDescription1(*wm_client()->tracker()->changes())[0]); EXPECT_TRUE(connection1_client->tracker()->changes()->empty()); @@ -436,7 +439,8 @@ TEST_F(WindowTreeTest, BasicInputEventTarget) { const WindowId embed_window_id(wm_connection()->id(), 1); - EXPECT_TRUE(wm_connection()->NewWindow(embed_window_id)); + EXPECT_TRUE( + wm_connection()->NewWindow(embed_window_id, ServerWindow::Properties())); EXPECT_TRUE(wm_connection()->SetWindowVisibility(embed_window_id, true)); EXPECT_TRUE( wm_connection()->AddWindow(*(wm_connection()->root()), embed_window_id)); @@ -461,8 +465,11 @@ ->SetBounds(gfx::Rect(0, 0, 50, 50)); const WindowId child1(connection1->id(), 1); - EXPECT_TRUE(connection1->NewWindow(child1)); + EXPECT_TRUE(connection1->NewWindow(child1, ServerWindow::Properties())); EXPECT_TRUE(connection1->AddWindow(embed_window_id, child1)); + connection1->GetHost()->AddActivationParent( + WindowIdToTransportId(embed_window_id)); + ServerWindow* v1 = connection1->GetWindow(child1); v1->SetVisible(true); v1->SetBounds(gfx::Rect(20, 20, 20, 20));
diff --git a/components/nacl/browser/pnacl_translation_cache.h b/components/nacl/browser/pnacl_translation_cache.h index bd14fca..4a3095e 100644 --- a/components/nacl/browser/pnacl_translation_cache.h +++ b/components/nacl/browser/pnacl_translation_cache.h
@@ -39,13 +39,13 @@ virtual ~PnaclTranslationCache(); // Initialize the translation cache in |cache_dir|. If the return value is - // net::ERR_IO_PENDING, |callback| will be called with a 0 argument on sucess + // net::ERR_IO_PENDING, |callback| will be called with a 0 argument on success // and <0 otherwise. int InitOnDisk(const base::FilePath& cache_dir, const CompletionCallback& callback); // Initialize the translation cache in memory. If the return value is - // net::ERR_IO_PENDING, |callback| will be called with a 0 argument on sucess + // net::ERR_IO_PENDING, |callback| will be called with a 0 argument on success // and <0 otherwise. int InitInMemory(const CompletionCallback& callback);
diff --git a/components/nacl/loader/nacl_ipc_adapter.cc b/components/nacl/loader/nacl_ipc_adapter.cc index 2f3eefc..b7d12cc 100644 --- a/components/nacl/loader/nacl_ipc_adapter.cc +++ b/components/nacl/loader/nacl_ipc_adapter.cc
@@ -227,6 +227,26 @@ DISALLOW_COPY_AND_ASSIGN(NaClDescWrapper); }; +scoped_ptr<NaClDescWrapper> MakeShmNaClDesc( + const base::SharedMemoryHandle& handle, + size_t size) { +#if defined(OS_MACOSX) + if (handle.GetType() == base::SharedMemoryHandle::MACH) { + return scoped_ptr<NaClDescWrapper>(new NaClDescWrapper( + NaClDescImcShmMachMake(handle.GetMemoryObject(), size))); + } + CHECK_EQ(base::SharedMemoryHandle::POSIX, handle.GetType()); +#endif + + return scoped_ptr<NaClDescWrapper>(new NaClDescWrapper(NaClDescImcShmMake( +#if defined(OS_WIN) + handle.GetHandle(), +#else + base::SharedMemory::GetFdFromSharedMemoryHandle(handle), +#endif + size))); +} + } // namespace class NaClIPCAdapter::RewrittenMessage @@ -541,15 +561,8 @@ scoped_ptr<NaClDescWrapper> nacl_desc; switch (iter->type()) { case ppapi::proxy::SerializedHandle::SHARED_MEMORY: { - const base::SharedMemoryHandle& shm_handle = iter->shmem(); - uint32_t size = iter->size(); - nacl_desc.reset(new NaClDescWrapper(NaClDescImcShmMake( -#if defined(OS_WIN) - shm_handle.GetHandle(), -#else - base::SharedMemory::GetFdFromSharedMemoryHandle(shm_handle), -#endif - static_cast<size_t>(size)))); + nacl_desc = + MakeShmNaClDesc(iter->shmem(), static_cast<size_t>(iter->size())); break; } case ppapi::proxy::SerializedHandle::SOCKET: { @@ -663,7 +676,7 @@ return; } - // The file token was sucessfully resolved. + // The file token was successfully resolved. std::string file_path_str = file_path.AsUTF8Unsafe(); base::PlatformFile handle = IPC::PlatformFileForTransitToPlatformFile(ipc_fd);
diff --git a/components/offline_pages/offline_page_model.cc b/components/offline_pages/offline_page_model.cc index 26de7168..242ade2 100644 --- a/components/offline_pages/offline_page_model.cc +++ b/components/offline_pages/offline_page_model.cc
@@ -251,6 +251,11 @@ callback)); } +bool OfflinePageModel::HasOfflinePages() const { + DCHECK(is_loaded_); + return !offline_pages_.empty(); +} + const std::vector<OfflinePageItem> OfflinePageModel::GetAllPages() const { DCHECK(is_loaded_); std::vector<OfflinePageItem> offline_pages; @@ -292,6 +297,16 @@ return nullptr; } +const OfflinePageItem* OfflinePageModel::GetPageByOnlineURL( + const GURL& online_url) const { + for (auto iter = offline_pages_.begin(); iter != offline_pages_.end(); + ++iter) { + if (iter->second.url == online_url) + return &(iter->second); + } + return nullptr; +} + void OfflinePageModel::CheckForExternalFileDeletion() { DCHECK(is_loaded_); @@ -477,8 +492,8 @@ const bookmarks::BookmarkNode* node) { // BookmarkNodeChanged could be triggered if title or URL gets changed. If // the latter, we need to invalidate the offline copy. - DCHECK(offline_pages_.count(node->id()) > 0); - if (offline_pages_[node->id()].url != node->url()) + auto iter = offline_pages_.find(node->id()); + if (iter != offline_pages_.end() && iter->second.url != node->url()) DeletePageByBookmarkId(node->id(), DeletePageCallback()); }
diff --git a/components/offline_pages/offline_page_model.h b/components/offline_pages/offline_page_model.h index c6e93f2e..631d522 100644 --- a/components/offline_pages/offline_page_model.h +++ b/components/offline_pages/offline_page_model.h
@@ -173,6 +173,9 @@ // Wipes out all the data by deleting all saved files and clearing the store. void ClearAll(const base::Closure& callback); + // Returns true if there're offline pages. + bool HasOfflinePages() const; + // Gets all available offline pages. Requires that the model is loaded. const std::vector<OfflinePageItem> GetAllPages() const; @@ -188,6 +191,10 @@ // returned if not found. const OfflinePageItem* GetPageByOfflineURL(const GURL& offline_url) const; + // Returns an offline page saved for |online_url|. A nullptr is returned if + // not found. + const OfflinePageItem* GetPageByOnlineURL(const GURL& online_url) const; + // Checks that all of the offline pages have corresponding offline copies. // If a page is discovered to be missing an offline copy, its offline page // metadata will be removed and |OfflinePageDeleted| will be sent to model @@ -201,6 +208,7 @@ private: FRIEND_TEST_ALL_PREFIXES(OfflinePageModelTest, MarkPageForDeletion); + FRIEND_TEST_ALL_PREFIXES(OfflinePageModelTest, BookmarkNodeChangesUrl); typedef ScopedVector<OfflinePageArchiver> PendingArchivers;
diff --git a/components/offline_pages/offline_page_model_unittest.cc b/components/offline_pages/offline_page_model_unittest.cc index b6b6a8a..cf661f9 100644 --- a/components/offline_pages/offline_page_model_unittest.cc +++ b/components/offline_pages/offline_page_model_unittest.cc
@@ -15,6 +15,7 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" +#include "components/bookmarks/browser/bookmark_node.h" #include "components/offline_pages/offline_page_item.h" #include "components/offline_pages/offline_page_metadata_store.h" #include "testing/gtest/include/gtest/gtest.h" @@ -388,10 +389,12 @@ BuildArchiver(kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) .Pass()); + EXPECT_FALSE(model()->HasOfflinePages()); model()->SavePage( kTestUrl, kTestPageBookmarkId1, archiver.Pass(), base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); PumpLoop(); + EXPECT_TRUE(model()->HasOfflinePages()); OfflinePageTestStore* store = GetStore(); EXPECT_EQ(kTestUrl, store->last_saved_page().url); @@ -843,6 +846,39 @@ EXPECT_FALSE(page); } +TEST_F(OfflinePageModelTest, GetPageByOnlineURL) { + scoped_ptr<OfflinePageTestArchiver> archiver( + BuildArchiver(kTestUrl, + OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) + .Pass()); + model()->SavePage( + kTestUrl, kTestPageBookmarkId1, archiver.Pass(), + base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); + PumpLoop(); + + scoped_ptr<OfflinePageTestArchiver> archiver2( + BuildArchiver(kTestUrl2, + OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) + .Pass()); + model()->SavePage( + kTestUrl2, kTestPageBookmarkId2, archiver2.Pass(), + base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); + PumpLoop(); + + const OfflinePageItem* page = model()->GetPageByOnlineURL(kTestUrl2); + EXPECT_TRUE(page); + EXPECT_EQ(kTestUrl2, page->url); + EXPECT_EQ(kTestPageBookmarkId2, page->bookmark_id); + + page = model()->GetPageByOnlineURL(kTestUrl); + EXPECT_TRUE(page); + EXPECT_EQ(kTestUrl, page->url); + EXPECT_EQ(kTestPageBookmarkId1, page->bookmark_id); + + page = model()->GetPageByOnlineURL(GURL("http://foo")); + EXPECT_FALSE(page); +} + // Test that model returns pages that are older than 30 days as candidates for // clean up, hence the numbers in time delta. TEST_F(OfflinePageModelTest, GetPagesToCleanUp) { @@ -950,4 +986,32 @@ EXPECT_EQ(1UL, GetStore()->offline_pages().size()); } +TEST_F(OfflinePageModelTest, BookmarkNodeChangesUrl) { + scoped_ptr<OfflinePageTestArchiver> archiver( + BuildArchiver(kTestUrl, + OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED) + .Pass()); + model()->SavePage( + kTestUrl, kTestPageBookmarkId1, archiver.Pass(), + base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr())); + PumpLoop(); + + EXPECT_EQ(1UL, model()->GetAllPages().size()); + + bookmarks::BookmarkNode bookmark_node(kTestPageBookmarkId1, kTestUrl2); + model()->BookmarkNodeChanged(nullptr, &bookmark_node); + PumpLoop(); + + // Offline copy should be removed. Chrome should not crash. + // http://crbug.com/558929 + EXPECT_EQ(0UL, model()->GetAllPages().size()); + + // Chrome should not crash when a bookmark with no offline copy is changed. + // http://crbug.com/560518 + bookmark_node.set_url(kTestUrl); + model()->BookmarkNodeChanged(nullptr, &bookmark_node); + PumpLoop(); + EXPECT_EQ(0UL, model()->GetAllPages().size()); +} + } // namespace offline_pages
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc index da77b1b..8136caa5 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -279,6 +279,15 @@ if (first_contentful_paint < background_delta) { PAGE_LOAD_HISTOGRAM(kHistogramFirstContentfulPaint, first_contentful_paint); + // Bucket these histograms into high/low resolution clock systems. This + // might point us to directions that will de-noise some UMA. + if (base::TimeTicks::IsHighResolution()) { + PAGE_LOAD_HISTOGRAM(kHistogramFirstContentfulPaintHigh, + first_contentful_paint); + } else { + PAGE_LOAD_HISTOGRAM(kHistogramFirstContentfulPaintLow, + first_contentful_paint); + } } else { PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstContentfulPaint, first_contentful_paint);
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.h b/components/page_load_metrics/browser/metrics_web_contents_observer.h index 7ad09b55..6bc2904 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.h +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.h
@@ -61,6 +61,11 @@ const char kBackgroundHistogramFirstContentfulPaint[] = "PageLoad.Timing2.NavigationToFirstContentfulPaint.Background"; +const char kHistogramFirstContentfulPaintHigh[] = + "PageLoad.Timing2.NavigationToFirstContentfulPaint.HighResolutionClock"; +const char kHistogramFirstContentfulPaintLow[] = + "PageLoad.Timing2.NavigationToFirstContentfulPaint.LowResolutionClock"; + const char kHistogramFirstBackground[] = "PageLoad.Timing2.NavigationToFirstBackground"; const char kHistogramFirstForeground[] =
diff --git a/components/password_manager/core/browser/password_manager_constants.cc b/components/password_manager/core/browser/password_manager_constants.cc index 4f9ebd1..392b024 100644 --- a/components/password_manager/core/browser/password_manager_constants.cc +++ b/components/password_manager/core/browser/password_manager_constants.cc
@@ -11,4 +11,7 @@ const base::FilePath::CharType kLoginDataFileName[] = FILE_PATH_LITERAL("Login Data"); +const char kPasswordManagerAccountDashboardURL[] = + "https://passwords.google.com/settings/passwords"; + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_constants.h b/components/password_manager/core/browser/password_manager_constants.h index 112ce7c..1631c915 100644 --- a/components/password_manager/core/browser/password_manager_constants.h +++ b/components/password_manager/core/browser/password_manager_constants.h
@@ -12,6 +12,9 @@ extern const base::FilePath::CharType kAffiliationDatabaseFileName[]; extern const base::FilePath::CharType kLoginDataFileName[]; +// URL to the password manager account dashboard. +extern const char kPasswordManagerAccountDashboardURL[]; + } // namespace password_manager #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_CONSTANTS_H_
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection.h b/components/proximity_auth/ble/bluetooth_low_energy_connection.h index 916f157f..a16a03a 100644 --- a/components/proximity_auth/ble/bluetooth_low_energy_connection.h +++ b/components/proximity_auth/ble/bluetooth_low_energy_connection.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 COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_LOW_ENERGY_CONNECTION_H -#define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_LOW_ENERGY_CONNECTION_H +#ifndef COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_H_ +#define COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_H_ #include <queue> #include <string> @@ -204,7 +204,7 @@ void ProcessNextWriteRequest(); // Called when the BluetoothGattCharacteristic::RemoteCharacteristicWrite() is - // sucessfully complete. + // successfully complete. void OnRemoteCharacteristicWritten(bool run_did_send_message_callback); // Called when there is an error writing to the remote characteristic @@ -306,4 +306,4 @@ } // namespace proximity_auth -#endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_LOW_ENERGY_CONNECTION_H +#endif // COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_H_
diff --git a/components/proximity_auth/cryptauth/pref_names.cc b/components/proximity_auth/cryptauth/pref_names.cc index fb89669..6336247 100644 --- a/components/proximity_auth/cryptauth/pref_names.cc +++ b/components/proximity_auth/cryptauth/pref_names.cc
@@ -12,7 +12,7 @@ const char kCryptAuthDeviceSyncIsRecoveringFromFailure[] = "cryptauth.device_sync.is_recovering_from_failure"; -// The timestamp of the last successfull CryptAuth device_sync in seconds. +// The timestamp of the last successful CryptAuth device_sync in seconds. const char kCryptAuthDeviceSyncLastSyncTimeSeconds[] = "cryptauth.device_sync.last_device_sync_time_seconds"; @@ -32,7 +32,7 @@ const char kCryptAuthEnrollmentIsRecoveringFromFailure[] = "cryptauth.enrollment.is_recovering_from_failure"; -// The timestamp of the last successfull CryptAuth enrollment in seconds. +// The timestamp of the last successful CryptAuth enrollment in seconds. const char kCryptAuthEnrollmentLastEnrollmentTimeSeconds[] = "cryptauth.enrollment.last_enrollment_time_seconds"; @@ -54,4 +54,4 @@ "cryptauth.gcm_registration_id"; } // namespace prefs -} // proximity_auth +} // namespace proximity_auth
diff --git a/components/proximity_auth/webui/resources/local-state.html b/components/proximity_auth/webui/resources/local-state.html index bd96b72a..3b6cb06 100644 --- a/components/proximity_auth/webui/resources/local-state.html +++ b/components/proximity_auth/webui/resources/local-state.html
@@ -69,9 +69,7 @@ <div class="card-content layout vertical flex"> <div class="card-title">Enrollment</div> <div class="card-subtitle"> - <span>[[ - getLastSyncTimeString_(enrollmentState_, "Never enrolled") - ]]</span> + <span>[[getLastSyncTimeString_(enrollmentState_, "Never enrolled")]]</span> </div> <div class="next-refresh layout horizontal center flex"> <iron-icon class="next-sync-icon"
diff --git a/components/security_interstitials/core/controller_client.cc b/components/security_interstitials/core/controller_client.cc index 7be4d84a..0baa07a 100644 --- a/components/security_interstitials/core/controller_client.cc +++ b/components/security_interstitials/core/controller_client.cc
@@ -13,6 +13,13 @@ namespace security_interstitials { +const char kBoxChecked[] = "boxchecked"; +const char kDisplayCheckBox[] = "displaycheckbox"; +const char kOptInLink[] = "optInLink"; +const char kPrivacyLinkHtml[] = + "<a id=\"privacy-link\" href=\"\" onclick=\"sendCommand(%d); " + "return false;\" onmousedown=\"return false;\">%s</a>"; + ControllerClient::ControllerClient() {} ControllerClient::~ControllerClient() {}
diff --git a/components/security_interstitials/core/controller_client.h b/components/security_interstitials/core/controller_client.h index 9b18284..6eb41e0 100644 --- a/components/security_interstitials/core/controller_client.h +++ b/components/security_interstitials/core/controller_client.h
@@ -17,37 +17,43 @@ class MetricsHelper; +// Constants used to communicate with the JavaScript. +extern const char kBoxChecked[]; +extern const char kDisplayCheckBox[]; +extern const char kOptInLink[]; +extern const char kPrivacyLinkHtml[]; + +// These represent the commands sent from the interstitial JavaScript. +// DO NOT reorder or change these without also changing the JavaScript! +// See components/security_interstitials/core/browser/resources/ +enum SecurityInterstitialCommands { + // Used by tests + CMD_ERROR = -3, + CMD_TEXT_FOUND = -2, + CMD_TEXT_NOT_FOUND = -1, + // Decisions + CMD_DONT_PROCEED = 0, + CMD_PROCEED = 1, + // Ways for user to get more information + CMD_SHOW_MORE_SECTION = 2, + CMD_OPEN_HELP_CENTER = 3, + CMD_OPEN_DIAGNOSTIC = 4, + // Primary button actions + CMD_RELOAD = 5, + CMD_OPEN_DATE_SETTINGS = 6, + CMD_OPEN_LOGIN = 7, + // Safe Browsing Extended Reporting + CMD_DO_REPORT = 8, + CMD_DONT_REPORT = 9, + CMD_OPEN_REPORTING_PRIVACY = 10, + // Report a phishing error + CMD_REPORT_PHISHING_ERROR = 11, +}; + // Provides methods for handling commands from the user, which requires some // embedder-specific abstraction. class ControllerClient { public: - // These represent the commands sent from the interstitial JavaScript. - // DO NOT reorder or change these without also changing the JavaScript! - // See components/security_interstitials/core/browser/resources/ - enum SecurityInterstitialCommands { - // Used by tests - CMD_ERROR = -3, - CMD_TEXT_FOUND = -2, - CMD_TEXT_NOT_FOUND = -1, - // Decisions - CMD_DONT_PROCEED = 0, - CMD_PROCEED = 1, - // Ways for user to get more information - CMD_SHOW_MORE_SECTION = 2, - CMD_OPEN_HELP_CENTER = 3, - CMD_OPEN_DIAGNOSTIC = 4, - // Primary button actions - CMD_RELOAD = 5, - CMD_OPEN_DATE_SETTINGS = 6, - CMD_OPEN_LOGIN = 7, - // Safe Browsing Extended Reporting - CMD_DO_REPORT = 8, - CMD_DONT_REPORT = 9, - CMD_OPEN_REPORTING_PRIVACY = 10, - // Report a phishing error - CMD_REPORT_PHISHING_ERROR = 11, - }; - ControllerClient(); virtual ~ControllerClient();
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index 4b2d4a0b..aa428fd 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -448,6 +448,7 @@ bool removed) { DCHECK_EQ(kGaiaCookieName, cookie.Name()); DCHECK_EQ(GaiaUrls::GetInstance()->google_url().host(), cookie.Domain()); + list_accounts_stale_ = true; // Ignore changes to the cookie while requests are pending. These changes // are caused by the service itself as it adds accounts. A side effects is // that any changes to the gaia cookie outside of this class, while requests @@ -459,8 +460,6 @@ signin_client_->DelayNetworkCall( base::Bind(&GaiaCookieManagerService::StartFetchingListAccounts, base::Unretained(this))); - } else { - list_accounts_stale_ = true; } }
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 78b5c289..e2fa05d8 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -556,6 +556,35 @@ "[\"f\", [[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]]]"); } +TEST_F(GaiaCookieManagerServiceTest, ListAccountsAfterOnCookieChanged) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + std::vector<gaia::ListedAccount> list_accounts; + std::vector<gaia::ListedAccount> empty_list_accounts; + + EXPECT_CALL(helper, StartFetchingListAccounts()); + EXPECT_CALL(observer, + OnGaiaAccountsInCookieUpdated(empty_list_accounts, no_error())); + ASSERT_FALSE(helper.ListAccounts(&list_accounts)); + ASSERT_TRUE(list_accounts.empty()); + SimulateListAccountsSuccess(&helper, "[\"f\",[]]"); + + // ListAccounts returns cached data. + ASSERT_TRUE(helper.ListAccounts(&list_accounts)); + ASSERT_TRUE(list_accounts.empty()); + + EXPECT_CALL(helper, StartFetchingListAccounts()); + EXPECT_CALL(observer, + OnGaiaAccountsInCookieUpdated(empty_list_accounts, no_error())); + helper.ForceOnCookieChangedProcessing(); + + // OnCookieChanged should invalidate cached data. + ASSERT_FALSE(helper.ListAccounts(&list_accounts)); + ASSERT_TRUE(list_accounts.empty()); + SimulateListAccountsSuccess(&helper, "[\"f\",[]]"); +} + TEST_F(GaiaCookieManagerServiceTest, ExternalCcResultFetcher) { InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); GaiaCookieManagerService::ExternalCcResultFetcher result_fetcher(&helper);
diff --git a/components/sync_driver/device_info_service.cc b/components/sync_driver/device_info_service.cc index 29a4d193..f210b2f8 100644 --- a/components/sync_driver/device_info_service.cc +++ b/components/sync_driver/device_info_service.cc
@@ -48,7 +48,7 @@ syncer::SyncError DeviceInfoService::ApplySyncChanges( syncer_v2::MetadataChanges* metadata_changes, - syncer_v2::EntityDataList entity_data_list) { + syncer_v2::EntityChangeList entity_changes) { // TODO(skym): Implementation. return syncer::SyncError(); }
diff --git a/components/sync_driver/device_info_service.h b/components/sync_driver/device_info_service.h index 4b658090..76a4126a 100644 --- a/components/sync_driver/device_info_service.h +++ b/components/sync_driver/device_info_service.h
@@ -47,7 +47,7 @@ syncer_v2::EntityDataList entity_data_list) override; syncer::SyncError ApplySyncChanges( syncer_v2::MetadataChanges* metadata_changes, - syncer_v2::EntityDataList entity_data_list) override; + syncer_v2::EntityChangeList entity_changes) override; void LoadMetadata(MetadataCallback callback) override; void GetData(ClientKeyList client_keys, DataCallback callback) override; void GetAllData(DataCallback callback) override;
diff --git a/components/tracing/child_trace_message_filter_browsertest.cc b/components/tracing/child_trace_message_filter_browsertest.cc index b7c83e2..2bbff08 100644 --- a/components/tracing/child_trace_message_filter_browsertest.cc +++ b/components/tracing/child_trace_message_filter_browsertest.cc
@@ -137,7 +137,7 @@ WaitForIPCMessage(TracingHostMsg_ProcessMemoryDumpResponse::ID); EXPECT_NE(nullptr, msg); - // Check that the |dump_guid| and the |sucess| fields are properly set. + // Check that the |dump_guid| and the |success| fields are properly set. TracingHostMsg_ProcessMemoryDumpResponse::Param params; TracingHostMsg_ProcessMemoryDumpResponse::Read(msg, ¶ms); const uint64 resp_guid = base::get<0>(params);
diff --git a/components/translate/content/renderer/translate_helper.cc b/components/translate/content/renderer/translate_helper.cc index 630778d..b42620a 100644 --- a/components/translate/content/renderer/translate_helper.cc +++ b/components/translate/content/renderer/translate_helper.cc
@@ -510,7 +510,7 @@ if (!IsTranslateLibReady()) { // The library is not ready, try again later, unless we have tried several - // times unsucessfully already. + // times unsuccessfully already. if (++count >= kMaxTranslateInitCheckAttempts) { NotifyBrowserTranslationFailed(TranslateErrors::INITIALIZATION_ERROR); return;
diff --git a/components/translate/ios/browser/ios_translate_driver.h b/components/translate/ios/browser/ios_translate_driver.h index 194f3e6..e54bd6aa 100644 --- a/components/translate/ios/browser/ios_translate_driver.h +++ b/components/translate/ios/browser/ios_translate_driver.h
@@ -64,7 +64,7 @@ void OpenUrlInNewTab(const GURL& url) override; private: - // Called when the translation was successfull. + // Called when the translation was successful. void TranslationDidSucceed(const std::string& source_lang, const std::string& target_lang, int page_seq_no,
diff --git a/components/user_manager/remove_user_delegate.h b/components/user_manager/remove_user_delegate.h index 1077bda..6659f0a 100644 --- a/components/user_manager/remove_user_delegate.h +++ b/components/user_manager/remove_user_delegate.h
@@ -7,16 +7,18 @@ #include "components/user_manager/user_manager_export.h" +class AccountId; + namespace user_manager { // Delegate to be used with |UserManager::RemoveUser|. class USER_MANAGER_EXPORT RemoveUserDelegate { public: // Called right before actual user removal process is initiated. - virtual void OnBeforeUserRemoved(const std::string& username) = 0; + virtual void OnBeforeUserRemoved(const AccountId& account_id) = 0; // Called right after user removal process has been initiated. - virtual void OnUserRemoved(const std::string& username) = 0; + virtual void OnUserRemoved(const AccountId& account_id) = 0; }; } // namespace user_manager
diff --git a/components/user_manager/user_manager.cc b/components/user_manager/user_manager.cc index 3cf3f267..869b366 100644 --- a/components/user_manager/user_manager.cc +++ b/components/user_manager/user_manager.cc
@@ -5,6 +5,8 @@ #include "components/user_manager/user_manager.h" #include "base/logging.h" +#include "chromeos/login/user_names.h" +#include "components/signin/core/account_id/account_id.h" namespace user_manager { @@ -85,4 +87,27 @@ return previous_instance; } +// static +AccountId UserManager::GetKnownUserAccountId(const std::string& user_email, + const std::string& gaia_id) { + // In tests empty accounts are possible. + if (user_email.empty() && gaia_id.empty()) + return EmptyAccountId(); + + if (user_email == chromeos::login::kStubUser) + return chromeos::login::StubAccountId(); + + if (user_email == chromeos::login::kGuestUserName) + return chromeos::login::GuestAccountId(); + + UserManager* user_manager = Get(); + if (user_manager) + return user_manager->GetKnownUserAccountIdImpl(user_email, gaia_id); + + // This is fallback for tests. + return (gaia_id.empty() + ? AccountId::FromUserEmail(user_email) + : AccountId::FromUserEmailGaiaId(user_email, gaia_id)); +} + } // namespace user_manager
diff --git a/components/user_manager/user_manager.h b/components/user_manager/user_manager.h index 03a08d7..59cbbd92 100644 --- a/components/user_manager/user_manager.h +++ b/components/user_manager/user_manager.h
@@ -363,10 +363,16 @@ const std::string& path, const int in_value) = 0; - // Returns true if user's AccountId was found. - // Returns it in |out_account_id|. - virtual bool GetKnownUserAccountId(const AccountId& authenticated_account_id, - AccountId* out_account_id) = 0; + // This call forms full account id of a known user by email and (optionally) + // gaia_id. + // This is a temporary call while migrating to AccountId. + virtual AccountId GetKnownUserAccountIdImpl(const std::string& user_email, + const std::string& gaia_id) = 0; + + // The same as above, but doesn't crash in unit_tests when Usermanager + // doesn't exist. + static AccountId GetKnownUserAccountId(const std::string& user_email, + const std::string& gaia_id); // Updates |gaia_id| for user with |account_id|. // TODO(alemate): Update this once AccountId contains GAIA ID
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc index f51d9b1..bdeb438 100644 --- a/components/user_manager/user_manager_base.cc +++ b/components/user_manager/user_manager_base.cc
@@ -99,12 +99,12 @@ const int kLogoutToLoginDelayMaxSec = 1800; // Callback that is called after user removal is complete. -void OnRemoveUserComplete(const std::string& user_email, +void OnRemoveUserComplete(const AccountId& account_id, bool success, cryptohome::MountError return_code) { // Log the error, but there's not much we can do. if (!success) { - LOG(ERROR) << "Removal of cryptohome for " << user_email + LOG(ERROR) << "Removal of cryptohome for " << account_id.Serialize() << " failed, return code: " << return_code; } } @@ -353,14 +353,13 @@ void UserManagerBase::RemoveNonOwnerUserInternal(const AccountId& account_id, RemoveUserDelegate* delegate) { if (delegate) - delegate->OnBeforeUserRemoved(account_id.GetUserEmail()); + delegate->OnBeforeUserRemoved(account_id); RemoveUserFromList(account_id); cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( - account_id.GetUserEmail(), - base::Bind(&OnRemoveUserComplete, account_id.GetUserEmail())); + account_id.GetUserEmail(), base::Bind(&OnRemoveUserComplete, account_id)); if (delegate) - delegate->OnUserRemoved(account_id.GetUserEmail()); + delegate->OnUserRemoved(account_id); } void UserManagerBase::RemoveUserFromList(const AccountId& account_id) { @@ -595,19 +594,7 @@ continue; } - const AccountId partial_account_id = AccountId::FromUserEmail(email); - AccountId account_id = EmptyAccountId(); - - const bool lookup_result = - GetKnownUserAccountId(partial_account_id, &account_id); - // TODO(alemate): - // DCHECK(lookup_result) << "KnownUser lookup falied for '" << email << "'"; - // (tests do not initialize KnownUserData) - - if (!lookup_result) { - account_id = partial_account_id; - LOG(WARNING) << "KnownUser lookup falied for '" << email << "'"; - } + const AccountId account_id = GetKnownUserAccountId(email, std::string()); if (existing_users.find(account_id) != existing_users.end() || !users_set->insert(account_id).second) { @@ -1042,6 +1029,7 @@ // Local State may not be initialized in tests. if (!local_state) return false; + if (IsUserNonCryptohomeDataEphemeral(account_id)) return false; @@ -1163,29 +1151,38 @@ UpdateKnownUserPrefs(account_id, dict, false); } -bool UserManagerBase::GetKnownUserAccountId( - const AccountId& authenticated_account_id, - AccountId* out_account_id) { - if (!authenticated_account_id.GetGaiaId().empty()) { - std::string canonical_email; - if (!GetKnownUserStringPref( - AccountId::FromGaiaId(authenticated_account_id.GetGaiaId()), - kCanonicalEmail, &canonical_email)) { - return false; - } +AccountId UserManagerBase::GetKnownUserAccountIdImpl( + const std::string& user_email, + const std::string& gaia_id) { + DCHECK(!(user_email.empty() && gaia_id.empty())); - *out_account_id = AccountId::FromUserEmailGaiaId( - canonical_email, authenticated_account_id.GetGaiaId()); - return true; + // We can have several users with the same gaia_id but different e-mails. + // The opposite case is not possible. + std::string stored_gaia_id; + const std::string sanitized_email = + user_email.empty() + ? std::string() + : gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_email)); + if (!sanitized_email.empty() && + GetKnownUserStringPref(AccountId::FromUserEmail(sanitized_email), + kGAIAIdKey, &stored_gaia_id)) { + if (!gaia_id.empty() && gaia_id != stored_gaia_id) + LOG(ERROR) << "User gaia id has changed. Sync will not work."; + + // gaia_id is associated with cryptohome. + return AccountId::FromUserEmailGaiaId(sanitized_email, stored_gaia_id); } - DCHECK(!authenticated_account_id.GetUserEmail().empty()); - std::string gaia_id; - if (!GetKnownUserStringPref(authenticated_account_id, kGAIAIdKey, &gaia_id)) - return false; - *out_account_id = AccountId::FromUserEmailGaiaId( - authenticated_account_id.GetUserEmail(), gaia_id); - return true; + std::string stored_email; + // GetKnownUserStringPref() returns the first user record that matches + // given ID. So we will get the first one if there are multiples. + if (!gaia_id.empty() && + GetKnownUserStringPref(AccountId::FromGaiaId(gaia_id), kCanonicalEmail, + &stored_email)) { + return AccountId::FromUserEmailGaiaId(stored_email, gaia_id); + } + + return AccountId::FromUserEmailGaiaId(sanitized_email, gaia_id); } void UserManagerBase::UpdateGaiaID(const AccountId& account_id,
diff --git a/components/user_manager/user_manager_base.h b/components/user_manager/user_manager_base.h index dd46c5d..138faf0 100644 --- a/components/user_manager/user_manager_base.h +++ b/components/user_manager/user_manager_base.h
@@ -129,8 +129,8 @@ void SetKnownUserIntegerPref(const AccountId& account_id, const std::string& path, int in_value) override; - bool GetKnownUserAccountId(const AccountId& authenticated_account_id, - AccountId* out_account_id) override; + AccountId GetKnownUserAccountIdImpl(const std::string& user_email, + const std::string& gaia_id) override; void UpdateGaiaID(const AccountId& account_id, const std::string& gaia_id) override; bool FindGaiaID(const AccountId& account_id, std::string* out_value) override;
diff --git a/components/web_cache.gypi b/components/web_cache.gypi index a42e344..53b0714 100644 --- a/components/web_cache.gypi +++ b/components/web_cache.gypi
@@ -31,13 +31,6 @@ ], # Disable c4267 warnings until we fix size_t to int truncations. 'msvs_disabled_warnings': [ 4267, ], - 'conditions': [ - ['OS=="win" and win_use_allocator_shim==1', { - 'dependencies': [ - '../base/allocator/allocator.gyp:allocator', - ], - }], - ], }, { 'target_name': 'web_cache_renderer',
diff --git a/content/app/android/content_main.cc b/content/app/android/content_main.cc index 74f6783..4eaa3a3 100644 --- a/content/app/android/content_main.cc +++ b/content/app/android/content_main.cc
@@ -28,12 +28,6 @@ } // namespace -static void InitApplicationContext(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - const JavaParamRef<jobject>& context) { - base::android::InitApplicationContext(env, context); -} - static jint Start(JNIEnv* env, const JavaParamRef<jclass>& clazz) { TRACE_EVENT0("startup", "content::Start");
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc index b352c3e..6a0ff33 100644 --- a/content/app/content_main_runner.cc +++ b/content/app/content_main_runner.cc
@@ -414,25 +414,6 @@ } #if defined(USE_TCMALLOC) - static bool GetAllocatorWasteSizeThunk(size_t* size) { - size_t heap_size, allocated_bytes, unmapped_bytes; - MallocExtension* ext = MallocExtension::instance(); - if (ext->GetNumericProperty("generic.heap_size", &heap_size) && - ext->GetNumericProperty("generic.current_allocated_bytes", - &allocated_bytes) && - ext->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes", - &unmapped_bytes)) { - *size = heap_size - allocated_bytes - unmapped_bytes; - return true; - } - DCHECK(false); - return false; - } - - static void GetStatsThunk(char* buffer, int buffer_length) { - MallocExtension::instance()->GetStats(buffer, buffer_length); - } - static bool GetNumericPropertyThunk(const char* name, size_t* value) { return MallocExtension::instance()->GetNumericProperty(name, value); } @@ -471,9 +452,6 @@ tc_set_new_mode(1); // On windows, we've already set these thunks up in _heap_init() - base::allocator::SetGetAllocatorWasteSizeFunction( - GetAllocatorWasteSizeThunk); - base::allocator::SetGetStatsFunction(GetStatsThunk); base::allocator::SetGetNumericPropertyFunction(GetNumericPropertyThunk); base::allocator::SetReleaseFreeMemoryFunction(ReleaseFreeMemoryThunk);
diff --git a/content/app/mojo/mojo_init.cc b/content/app/mojo/mojo_init.cc index 8a402bc4..2b520b7 100644 --- a/content/app/mojo/mojo_init.cc +++ b/content/app/mojo/mojo_init.cc
@@ -4,8 +4,10 @@ #include "content/app/mojo/mojo_init.h" +#include "base/command_line.h" #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" +#include "content/public/common/content_switches.h" #include "ipc/ipc_channel.h" #include "third_party/mojo/src/mojo/edk/embedder/embedder.h" @@ -16,6 +18,20 @@ class MojoInitializer { public: MojoInitializer() { +#if defined(OS_WIN) + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch("use-new-edk")) { + std::string process_type = + command_line.GetSwitchValueASCII(switches::kProcessType); + if (process_type.empty()) { + mojo::embedder::PreInitializeParentProcess(); + } else { + mojo::embedder::PreInitializeChildProcess(); + } + } +#endif + mojo::embedder::SetMaxMessageSize(IPC::Channel::kMaximumMessageSize); mojo::embedder::Init(); }
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 84cf94c6..1c43b802 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -1949,10 +1949,12 @@ if (!browserAccessibility_) return NO; - if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) + if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { if ([self internalRole] == ui::AX_ROLE_DATE_TIME) return NO; return GetState(browserAccessibility_, ui::AX_STATE_FOCUSABLE); + } + if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { return browserAccessibility_->GetBoolAttribute( ui::AX_ATTR_CAN_SET_VALUE);
diff --git a/content/browser/android/in_process/DEPS b/content/browser/android/in_process/DEPS index 868afbe..e200a5aa 100644 --- a/content/browser/android/in_process/DEPS +++ b/content/browser/android/in_process/DEPS
@@ -3,5 +3,6 @@ # Required for SynchronousCompositor (in --single-process mode only). "+content/public/renderer/android", "+content/renderer", + "+ui/events/blink/synchronous_input_handler_proxy.h", # Include boliu@chromium.org on the review for any additions to this file. ]
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc index b07e2229..ae4fb61 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -114,7 +114,7 @@ void SynchronousCompositorImpl::DidInitializeRendererObjects( SynchronousCompositorOutputSurface* output_surface, SynchronousCompositorExternalBeginFrameSource* begin_frame_source, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { DCHECK(!output_surface_); DCHECK(!begin_frame_source_); DCHECK(output_surface);
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.h b/content/browser/android/in_process/synchronous_compositor_impl.h index 099fe26..da2e15d 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.h +++ b/content/browser/android/in_process/synchronous_compositor_impl.h
@@ -13,8 +13,8 @@ #include "content/browser/android/synchronous_compositor_base.h" #include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h" #include "content/renderer/android/synchronous_compositor_output_surface.h" -#include "content/renderer/input/synchronous_input_handler_proxy.h" #include "ipc/ipc_message.h" +#include "ui/events/blink/synchronous_input_handler_proxy.h" namespace cc { class InputHandler; @@ -32,7 +32,7 @@ // This class is created on the main thread but most of the APIs are called // from the Compositor thread. class SynchronousCompositorImpl - : public SynchronousInputHandler, + : public ui::SynchronousInputHandler, public SynchronousCompositorBase, public SynchronousCompositorExternalBeginFrameSourceClient, public SynchronousCompositorOutputSurfaceClient { @@ -50,7 +50,7 @@ void DidInitializeRendererObjects( SynchronousCompositorOutputSurface* output_surface, SynchronousCompositorExternalBeginFrameSource* begin_frame_source, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy); + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy); void DidDestroyRendererObjects(); // SynchronousCompositorExternalBeginFrameSourceClient overrides. @@ -109,7 +109,7 @@ SynchronousCompositorClient* const compositor_client_; SynchronousCompositorOutputSurface* output_surface_; SynchronousCompositorExternalBeginFrameSource* begin_frame_source_; - SynchronousInputHandlerProxy* synchronous_input_handler_proxy_; + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy_; bool registered_with_client_; bool is_active_; bool renderer_needs_begin_frames_;
diff --git a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.cc b/content/browser/android/in_process/synchronous_compositor_registry_in_proc.cc index 5206cd3..4292a87 100644 --- a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.cc +++ b/content/browser/android/in_process/synchronous_compositor_registry_in_proc.cc
@@ -108,7 +108,7 @@ void SynchronousCompositorRegistryInProc::RegisterInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { DCHECK(CalledOnValidThread()); DCHECK(synchronous_input_handler_proxy); Entry& entry = entry_map_[routing_id];
diff --git a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.h b/content/browser/android/in_process/synchronous_compositor_registry_in_proc.h index 397bf8c..c475f97 100644 --- a/content/browser/android/in_process/synchronous_compositor_registry_in_proc.h +++ b/content/browser/android/in_process/synchronous_compositor_registry_in_proc.h
@@ -8,9 +8,10 @@ #include "base/containers/hash_tables.h" #include "base/lazy_instance.h" #include "content/renderer/android/synchronous_compositor_registry.h" +#include "ui/events/blink/synchronous_input_handler_proxy.h" -namespace cc { -class InputHandler; +namespace ui { +class SynchronousInputHandlerProxy; } namespace content { @@ -18,7 +19,6 @@ class SynchronousCompositorExternalBeginFrameSource; class SynchronousCompositorImpl; class SynchronousCompositorOutputSurface; -class SynchronousInputHandlerProxy; class SynchronousCompositorRegistryInProc : public SynchronousCompositorRegistry { @@ -31,7 +31,7 @@ SynchronousCompositorImpl* compositor); void RegisterInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy); + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy); void UnregisterInputHandler(int routing_id); // SynchronousCompositorRegistry overrides. @@ -58,7 +58,7 @@ SynchronousCompositorImpl* compositor; SynchronousCompositorExternalBeginFrameSource* begin_frame_source; SynchronousCompositorOutputSurface* output_surface; - SynchronousInputHandlerProxy* synchronous_input_handler_proxy; + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy; Entry(); bool IsReady();
diff --git a/content/browser/android/in_process/synchronous_input_event_filter.cc b/content/browser/android/in_process/synchronous_input_event_filter.cc index cbbcb2f..3ce1c61 100644 --- a/content/browser/android/in_process/synchronous_input_event_filter.cc +++ b/content/browser/android/in_process/synchronous_input_event_filter.cc
@@ -8,6 +8,7 @@ #include "content/browser/android/in_process/synchronous_compositor_impl.h" #include "content/browser/android/in_process/synchronous_compositor_registry_in_proc.h" #include "content/public/browser/browser_thread.h" +#include "ui/events/blink/synchronous_input_handler_proxy.h" #include "ui/events/latency_info.h" using blink::WebInputEvent; @@ -47,7 +48,7 @@ void SynchronousInputEventFilter::DidAddInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); SynchronousCompositorRegistryInProc::GetInstance()->RegisterInputHandler( routing_id, synchronous_input_handler_proxy);
diff --git a/content/browser/android/in_process/synchronous_input_event_filter.h b/content/browser/android/in_process/synchronous_input_event_filter.h index 89feee1..90e581c 100644 --- a/content/browser/android/in_process/synchronous_input_event_filter.h +++ b/content/browser/android/in_process/synchronous_input_event_filter.h
@@ -16,6 +16,10 @@ class WebInputEvent; } +namespace ui { +class SynchronousInputHandlerProxy; +} + namespace content { // This class perform synchronous, in-process InputEvent handling. @@ -35,7 +39,8 @@ void SetBoundHandler(const Handler& handler) override; void DidAddInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) override; + ui::SynchronousInputHandlerProxy* + synchronous_input_handler_proxy) override; void DidRemoveInputHandler(int routing_id) override; void DidOverscroll(int routing_id, const DidOverscrollParams& params) override;
diff --git a/content/browser/android/url_request_content_job.cc b/content/browser/android/url_request_content_job.cc index 6e661a2..1bcbf210 100644 --- a/content/browser/android/url_request_content_job.cc +++ b/content/browser/android/url_request_content_job.cc
@@ -11,7 +11,6 @@ #include "base/task_runner.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" -#include "net/base/net_errors.h" #include "net/http/http_util.h" #include "net/url_request/url_request_error_job.h" #include "url/gurl.h" @@ -34,6 +33,7 @@ content_path_(content_path), stream_(new net::FileStream(content_task_runner)), content_task_runner_(content_task_runner), + range_parse_result_(net::OK), remaining_bytes_(0), io_pending_(false), weak_ptr_factory_(this) {} @@ -56,43 +56,28 @@ net::URLRequestJob::Kill(); } -bool URLRequestContentJob::ReadRawData(net::IOBuffer* dest, - int dest_size, - int* bytes_read) { +int URLRequestContentJob::ReadRawData(net::IOBuffer* dest, int dest_size) { DCHECK_GT(dest_size, 0); - DCHECK(bytes_read); DCHECK_GE(remaining_bytes_, 0); if (remaining_bytes_ < dest_size) - dest_size = static_cast<int>(remaining_bytes_); + dest_size = remaining_bytes_; // If we should copy zero bytes because |remaining_bytes_| is zero, short // circuit here. - if (!dest_size) { - *bytes_read = 0; - return true; - } + if (!dest_size) + return 0; - int rv = - stream_->Read(dest, dest_size, base::Bind(&URLRequestContentJob::DidRead, - weak_ptr_factory_.GetWeakPtr(), - make_scoped_refptr(dest))); - if (rv >= 0) { - // Data is immediately available. - *bytes_read = rv; - remaining_bytes_ -= rv; - DCHECK_GE(remaining_bytes_, 0); - return true; - } - - // Otherwise, a read error occured. We may just need to wait... + int rv = stream_->Read(dest, dest_size, + base::Bind(&URLRequestContentJob::DidRead, + weak_ptr_factory_.GetWeakPtr())); if (rv == net::ERR_IO_PENDING) { io_pending_ = true; - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - } else { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, rv)); + } else if (rv > 0) { + remaining_bytes_ -= rv; } - return false; + DCHECK_GE(remaining_bytes_, 0); + return rv; } bool URLRequestContentJob::IsRedirectResponse(GURL* location, @@ -115,15 +100,16 @@ if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) return; - // We only care about "Range" header here. + // Currently this job only cares about the Range header. Note that validation + // is deferred to DidOpen(), because NotifyStartError is not legal to call + // since the job has not started. std::vector<net::HttpByteRange> ranges; if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { if (ranges.size() == 1) { byte_range_ = ranges[0]; } else { // We don't support multiple range requests. - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; } } } @@ -160,13 +146,20 @@ void URLRequestContentJob::DidOpen(int result) { if (result != net::OK) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + NotifyStartError( + net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + return; + } + + if (range_parse_result_ != net::OK) { + NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, + range_parse_result_)); return; } if (!byte_range_.ComputeBounds(meta_info_.content_size)) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyStartError(net::URLRequestStatus( + net::URLRequestStatus::FAILED, net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -193,8 +186,8 @@ void URLRequestContentJob::DidSeek(int64 result) { if (result != byte_range_.first_byte_position()) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyStartError(net::URLRequestStatus( + net::URLRequestStatus::FAILED, net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -202,24 +195,16 @@ NotifyHeadersComplete(); } -void URLRequestContentJob::DidRead(scoped_refptr<net::IOBuffer> buf, - int result) { +void URLRequestContentJob::DidRead(int result) { + DCHECK(io_pending_); + io_pending_ = false; + if (result > 0) { - SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status remaining_bytes_ -= result; DCHECK_GE(remaining_bytes_, 0); } - DCHECK(io_pending_); - io_pending_ = false; - - if (result == 0) { - NotifyDone(net::URLRequestStatus()); - } else if (result < 0) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); - } - - NotifyReadComplete(result); + ReadRawDataComplete(result); } } // namespace content
diff --git a/content/browser/android/url_request_content_job.h b/content/browser/android/url_request_content_job.h index 5d3d9336..dad9fbfc 100644 --- a/content/browser/android/url_request_content_job.h +++ b/content/browser/android/url_request_content_job.h
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" +#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_job.h" @@ -42,7 +43,7 @@ // net::URLRequestJob: void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; bool GetMimeType(std::string* mime_type) const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; @@ -79,7 +80,7 @@ void DidSeek(int64 result); // Callback after data is asynchronously read from the content URI into |buf|. - void DidRead(scoped_refptr<net::IOBuffer> buf, int result); + void DidRead(int result); // The full path of the content URI. base::FilePath content_path_; @@ -89,6 +90,7 @@ const scoped_refptr<base::TaskRunner> content_task_runner_; net::HttpByteRange byte_range_; + net::Error range_parse_result_; int64 remaining_bytes_; bool io_pending_;
diff --git a/content/browser/appcache/appcache_url_request_job.cc b/content/browser/appcache/appcache_url_request_job.cc index 82997f7..de924a1 100644 --- a/content/browser/appcache/appcache_url_request_job.cc +++ b/content/browser/appcache/appcache_url_request_job.cc
@@ -341,7 +341,6 @@ void AppCacheURLRequestJob::OnReadComplete(int result) { DCHECK(is_delivering_appcache_response()); if (result == 0) { - NotifyDone(net::URLRequestStatus()); AppCacheHistograms::CountResponseRetrieval( true, is_main_resource_, manifest_url_.GetOrigin()); } else if (result < 0) { @@ -349,13 +348,10 @@ storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_, entry_.response_id()); } - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); AppCacheHistograms::CountResponseRetrieval( false, is_main_resource_, manifest_url_.GetOrigin()); - } else { - SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status } - NotifyReadComplete(result); + ReadRawDataComplete(result); } // net::URLRequestJob overrides ------------------------------------------------ @@ -424,18 +420,14 @@ return http_info()->headers->response_code(); } -bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { DCHECK(is_delivering_appcache_response()); DCHECK_NE(buf_size, 0); - DCHECK(bytes_read); DCHECK(!reader_->IsReadPending()); reader_->ReadData(buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadComplete, base::Unretained(this))); - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; + return net::ERR_IO_PENDING; } void AppCacheURLRequestJob::SetExtraRequestHeaders(
diff --git a/content/browser/appcache/appcache_url_request_job.h b/content/browser/appcache/appcache_url_request_job.h index 95a3e18..8f51e7b 100644 --- a/content/browser/appcache/appcache_url_request_job.h +++ b/content/browser/appcache/appcache_url_request_job.h
@@ -148,7 +148,7 @@ net::LoadState GetLoadState() const override; bool GetCharset(std::string* charset) override; void GetResponseInfo(net::HttpResponseInfo* info) override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; // Sets extra request headers for Job types that support request headers. // This is how we get informed of range-requests.
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 97b637fe..071b97a 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -174,17 +174,9 @@ const StatusAndRegistrationCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - // For UMA, determine here whether the sync could fire immediately - BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire = - AreOptionConditionsMet(options) - ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE - : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE; - if (disabled_) { - BackgroundSyncMetrics::CountRegister( - options.periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE, - BACKGROUND_SYNC_STATUS_STORAGE_ERROR); + BackgroundSyncMetrics::CountRegisterFailure( + options.periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR); PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback); return; } @@ -407,17 +399,9 @@ const StatusAndRegistrationCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - // For UMA, determine here whether the sync could fire immediately - BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire = - AreOptionConditionsMet(options) - ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE - : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE; - if (disabled_) { - BackgroundSyncMetrics::CountRegister( - options.periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE, - BACKGROUND_SYNC_STATUS_STORAGE_ERROR); + BackgroundSyncMetrics::CountRegisterFailure( + options.periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR); PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback); return; } @@ -430,10 +414,8 @@ } if (options.tag.length() > kMaxTagLength) { - BackgroundSyncMetrics::CountRegister( - options.periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE, - BACKGROUND_SYNC_STATUS_NOT_ALLOWED); + BackgroundSyncMetrics::CountRegisterFailure( + options.periodicity, BACKGROUND_SYNC_STATUS_NOT_ALLOWED); PostErrorResponse(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, callback); return; } @@ -441,10 +423,8 @@ ServiceWorkerRegistration* sw_registration = service_worker_context_->GetLiveRegistration(sw_registration_id); if (!sw_registration || !sw_registration->active_version()) { - BackgroundSyncMetrics::CountRegister( - options.periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE, - BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER); + BackgroundSyncMetrics::CountRegisterFailure( + options.periodicity, BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER); PostErrorResponse(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER, callback); return; } @@ -468,11 +448,14 @@ BackgroundSyncRegistration* existing_registration = existing_registration_ref->value(); - // Record the duplicated registration - BackgroundSyncMetrics::CountRegister( - existing_registration->options()->periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE, - BACKGROUND_SYNC_STATUS_OK); + BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire = + AreOptionConditionsMet(options) + ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE + : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE; + BackgroundSyncMetrics::CountRegisterSuccess( + existing_registration->options()->periodicity, + registration_could_fire, + BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE); if (existing_registration->IsFiring()) { existing_registration->set_sync_state( @@ -646,17 +629,10 @@ const BackgroundSyncRegistration* new_registration = new_registration_ref->value(); - // For UMA, determine here whether the sync could fire immediately - BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire = - AreOptionConditionsMet(*new_registration->options()) - ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE - : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE; - if (status == SERVICE_WORKER_ERROR_NOT_FOUND) { // The service worker registration is gone. - BackgroundSyncMetrics::CountRegister( - new_registration->options()->periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE, + BackgroundSyncMetrics::CountRegisterFailure( + new_registration->options()->periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR); active_registrations_.erase(sw_registration_id); PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback); @@ -666,9 +642,8 @@ if (status != SERVICE_WORKER_OK) { LOG(ERROR) << "BackgroundSync failed to store registration due to backend " "failure."; - BackgroundSyncMetrics::CountRegister( - new_registration->options()->periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE, + BackgroundSyncMetrics::CountRegisterFailure( + new_registration->options()->periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR); DisableAndClearManager(base::Bind( callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR, @@ -676,10 +651,14 @@ return; } - BackgroundSyncMetrics::CountRegister( + BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire = + AreOptionConditionsMet(*new_registration->options()) + ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE + : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE; + BackgroundSyncMetrics::CountRegisterSuccess( new_registration->options()->periodicity, registration_could_fire, - BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE, - BACKGROUND_SYNC_STATUS_OK); + BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE); + FireReadyEvents(); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE,
diff --git a/content/browser/background_sync/background_sync_metrics.cc b/content/browser/background_sync/background_sync_metrics.cc index 4bfef5c9..dddec9b 100644 --- a/content/browser/background_sync/background_sync_metrics.cc +++ b/content/browser/background_sync/background_sync_metrics.cc
@@ -32,6 +32,7 @@ namespace content { +// static void BackgroundSyncMetrics::RecordEventResult(SyncPeriodicity periodicity, bool success, bool finished_in_foreground) { @@ -52,6 +53,7 @@ NOTREACHED(); } +// static void BackgroundSyncMetrics::RecordBatchSyncEventComplete( const base::TimeDelta& time, int number_of_batched_sync_events) { @@ -64,14 +66,15 @@ number_of_batched_sync_events); } -void BackgroundSyncMetrics::CountRegister( +// static +void BackgroundSyncMetrics::CountRegisterSuccess( SyncPeriodicity periodicity, RegistrationCouldFire registration_could_fire, - RegistrationIsDuplicate registration_is_duplicate, - BackgroundSyncStatus result) { + RegistrationIsDuplicate registration_is_duplicate) { switch (periodicity) { case SYNC_ONE_SHOT: - UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot", result, + UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot", + BACKGROUND_SYNC_STATUS_OK, BACKGROUND_SYNC_STATUS_MAX + 1); UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Registration.OneShot.CouldFire", registration_could_fire == REGISTRATION_COULD_FIRE); @@ -80,7 +83,8 @@ registration_is_duplicate == REGISTRATION_IS_DUPLICATE); return; case SYNC_PERIODIC: - UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.Periodic", result, + UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.Periodic", + BACKGROUND_SYNC_STATUS_OK, BACKGROUND_SYNC_STATUS_MAX + 1); UMA_HISTOGRAM_BOOLEAN( "BackgroundSync.Registration.Periodic.IsDuplicate", @@ -90,6 +94,23 @@ NOTREACHED(); } +// static +void BackgroundSyncMetrics::CountRegisterFailure(SyncPeriodicity periodicity, + BackgroundSyncStatus result) { + switch (periodicity) { + case SYNC_ONE_SHOT: + UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot", result, + BACKGROUND_SYNC_STATUS_MAX + 1); + return; + case SYNC_PERIODIC: + UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.Periodic", result, + BACKGROUND_SYNC_STATUS_MAX + 1); + return; + } + NOTREACHED(); +} + +// static void BackgroundSyncMetrics::CountUnregister(SyncPeriodicity periodicity, BackgroundSyncStatus result) { switch (periodicity) {
diff --git a/content/browser/background_sync/background_sync_metrics.h b/content/browser/background_sync/background_sync_metrics.h index 440ce3f..2c958b3 100644 --- a/content/browser/background_sync/background_sync_metrics.h +++ b/content/browser/background_sync/background_sync_metrics.h
@@ -38,13 +38,17 @@ static void RecordBatchSyncEventComplete(const base::TimeDelta& time, int number_of_batched_sync_events); - // Records the result of trying to register a sync. |could_fire| indicates - // whether the conditions were sufficient for the sync to fire immediately at - // the time it was registered. - static void CountRegister(SyncPeriodicity periodicity, - RegistrationCouldFire could_fire, - RegistrationIsDuplicate registration_is_duplicate, - BackgroundSyncStatus result); + // Records the result of successfully registering a sync. |could_fire| + // indicates whether the conditions were sufficient for the sync to fire + // immediately at the time it was registered. + static void CountRegisterSuccess( + SyncPeriodicity periodicity, + RegistrationCouldFire could_fire, + RegistrationIsDuplicate registration_is_duplicate); + + // Records the status of a failed sync registration. + static void CountRegisterFailure(SyncPeriodicity periodicity, + BackgroundSyncStatus status); // Records the result of trying to unregister a sync. static void CountUnregister(SyncPeriodicity periodicity,
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc index b871aa92..148054c3 100644 --- a/content/browser/browser_child_process_host_impl.cc +++ b/content/browser/browser_child_process_host_impl.cc
@@ -21,6 +21,7 @@ #include "content/browser/profiler_message_filter.h" #include "content/browser/tracing/trace_message_filter.h" #include "content/common/child_process_host_impl.h" +#include "content/common/child_process_messages.h" #include "content/public/browser/browser_child_process_host_delegate.h" #include "content/public/browser/browser_child_process_observer.h" #include "content/public/browser/browser_thread.h" @@ -31,6 +32,7 @@ #include "content/public/common/result_codes.h" #include "ipc/attachment_broker.h" #include "ipc/attachment_broker_privileged.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #if defined(OS_MACOSX) #include "content/browser/mach_broker_mac.h" @@ -400,6 +402,12 @@ DCHECK(process.IsValid()); #if defined(OS_WIN) + if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { + HANDLE client_pipe = mojo::embedder::ChildProcessLaunched(process.Handle()); + Send(new ChildProcessMsg_SetMojoParentPipeHandle( + IPC::GetFileHandleForProcess(client_pipe, process.Handle(), true))); + } + // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the // child process exits. This watcher is stopped once the IPC channel is // connected and the exit of the child process is detecter by an error on the
diff --git a/content/browser/cache_storage/cache_storage_manager.cc b/content/browser/cache_storage/cache_storage_manager.cc index 939797d7..84bb8e9 100644 --- a/content/browser/cache_storage/cache_storage_manager.cc +++ b/content/browser/cache_storage/cache_storage_manager.cc
@@ -126,13 +126,7 @@ return manager.Pass(); } -CacheStorageManager::~CacheStorageManager() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - for (CacheStorageMap::iterator it = cache_storage_map_.begin(); - it != cache_storage_map_.end(); ++it) { - delete it->second; - } -} +CacheStorageManager::~CacheStorageManager() = default; void CacheStorageManager::OpenCache( const GURL& origin, @@ -294,7 +288,13 @@ const storage::QuotaClient::DeletionCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin); + CacheStorageMap::iterator it = cache_storage_map_.find(origin); + if (it == cache_storage_map_.end()) { + callback.Run(storage::kQuotaStatusOk); + return; + } + + CacheStorage* cache_storage = it->second.release(); cache_storage_map_.erase(origin); cache_storage->CloseAllCaches( base::Bind(&CacheStorageManager::DeleteOriginDidClose, origin, callback, @@ -361,11 +361,11 @@ ConstructOriginPath(root_path_, origin), IsMemoryBacked(), cache_task_runner_.get(), request_context_getter_, quota_manager_proxy_, blob_context_, origin); - // The map owns fetch_stores. - cache_storage_map_.insert(std::make_pair(origin, cache_storage)); + cache_storage_map_.insert( + std::make_pair(origin, make_scoped_ptr(cache_storage))); return cache_storage; } - return it->second; + return it->second.get(); } // static
diff --git a/content/browser/cache_storage/cache_storage_manager.h b/content/browser/cache_storage/cache_storage_manager.h index 2d83a654..6f2dc16 100644 --- a/content/browser/cache_storage/cache_storage_manager.h +++ b/content/browser/cache_storage/cache_storage_manager.h
@@ -91,7 +91,7 @@ friend class CacheStorageMigrationTest; friend class CacheStorageQuotaClient; - typedef std::map<GURL, CacheStorage*> CacheStorageMap; + typedef std::map<GURL, scoped_ptr<CacheStorage>> CacheStorageMap; CacheStorageManager( const base::FilePath& path,
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 2b9cd696..5c08731 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -53,6 +53,10 @@ #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" +#if defined(MOJO_RUNNER_CLIENT) +#include "content/common/mojo/mojo_shell_connection_impl.h" +#endif + #if defined(OS_WIN) #include "content/browser/compositor/software_output_device_win.h" #elif defined(USE_OZONE) @@ -150,8 +154,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice( ui::Compositor* compositor) { #if defined(MOJO_RUNNER_CLIENT) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - "mojo-platform-channel-handle")) { + if (IsRunningInMojoShell()) { return scoped_ptr<cc::SoftwareOutputDevice>( new SoftwareOutputDeviceMus(compositor)); } @@ -204,9 +207,7 @@ #if defined(MOJO_RUNNER_CLIENT) // Chrome running as a mojo app currently can only use software compositing. // TODO(rjkroege): http://crbug.com/548451 - // TODO(rjkroege): Make IsRunningInMojoRunner callable from content. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - "mojo-platform-channel-handle")) { + if (IsRunningInMojoShell()) { return false; } #endif
diff --git a/content/browser/compositor/software_output_device_ozone.cc b/content/browser/compositor/software_output_device_ozone.cc index 0476ccb..e53935ac 100644 --- a/content/browser/compositor/software_output_device_ozone.cc +++ b/content/browser/compositor/software_output_device_ozone.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "content/browser/compositor/software_output_device_ozone.h" -#include "third_party/skia/include/core/SkDevice.h" #include "ui/compositor/compositor.h" #include "ui/gfx/skia_util.h" #include "ui/gfx/vsync_provider.h"
diff --git a/content/browser/compositor/software_output_device_ozone_unittest.cc b/content/browser/compositor/software_output_device_ozone_unittest.cc index 569d33c..030d2de 100644 --- a/content/browser/compositor/software_output_device_ozone_unittest.cc +++ b/content/browser/compositor/software_output_device_ozone_unittest.cc
@@ -7,8 +7,7 @@ #include "base/thread_task_runner_handle.h" #include "content/browser/compositor/software_output_device_ozone.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkDevice.h" -#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "ui/compositor/compositor.h" #include "ui/compositor/test/context_factories_for_test.h" #include "ui/gfx/geometry/size.h" @@ -125,8 +124,8 @@ output_device_->Resize(size, 1.f); SkCanvas* canvas = output_device_->BeginPaint(damage); - gfx::Size canvas_size(canvas->getDeviceSize().width(), - canvas->getDeviceSize().height()); + gfx::Size canvas_size(canvas->getBaseLayerSize().width(), + canvas->getBaseLayerSize().height()); EXPECT_EQ(size.ToString(), canvas_size.ToString()); size.SetSize(1000, 500); @@ -134,8 +133,8 @@ output_device_->Resize(size, 1.f); canvas = output_device_->BeginPaint(damage); - canvas_size.SetSize(canvas->getDeviceSize().width(), - canvas->getDeviceSize().height()); + canvas_size.SetSize(canvas->getBaseLayerSize().width(), + canvas->getBaseLayerSize().height()); EXPECT_EQ(size.ToString(), canvas_size.ToString()); }
diff --git a/content/browser/compositor/software_output_device_win.cc b/content/browser/compositor/software_output_device_win.cc index b4a41ee..a712def 100644 --- a/content/browser/compositor/software_output_device_win.cc +++ b/content/browser/compositor/software_output_device_win.cc
@@ -9,8 +9,6 @@ #include "cc/resources/shared_bitmap.h" #include "content/public/browser/browser_thread.h" #include "skia/ext/platform_canvas.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkDevice.h" #include "ui/compositor/compositor.h" #include "ui/gfx/gdi_util.h" #include "ui/gfx/skia_util.h"
diff --git a/content/browser/compositor/software_output_device_x11.cc b/content/browser/compositor/software_output_device_x11.cc index f0719781..b611639 100644 --- a/content/browser/compositor/software_output_device_x11.cc +++ b/content/browser/compositor/software_output_device_x11.cc
@@ -8,8 +8,7 @@ #include <X11/Xutil.h> #include "content/public/browser/browser_thread.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkDevice.h" +#include "third_party/skia/include/core/SkImageInfo.h" #include "ui/base/x/x11_util.h" #include "ui/base/x/x11_util_internal.h" #include "ui/compositor/compositor.h"
diff --git a/content/browser/download/download_resource_handler.cc b/content/browser/download/download_resource_handler.cc index d806d944..2b6ac35 100644 --- a/content/browser/download/download_resource_handler.cc +++ b/content/browser/download/download_resource_handler.cc
@@ -499,7 +499,7 @@ void DownloadResourceHandler::CancelRequest() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - const ResourceRequestInfo* info = GetRequestInfo(); + const ResourceRequestInfoImpl* info = GetRequestInfo(); ResourceDispatcherHostImpl::Get()->CancelRequest( info->GetChildID(), info->GetRequestID()); @@ -507,7 +507,7 @@ } std::string DownloadResourceHandler::DebugString() const { - const ResourceRequestInfo* info = GetRequestInfo(); + const ResourceRequestInfoImpl* info = GetRequestInfo(); return base::StringPrintf("{" " url_ = " "\"%s\"" " info = {"
diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc index 6ade20f..f2ebfd87 100644 --- a/content/browser/download/mhtml_generation_browsertest.cc +++ b/content/browser/download/mhtml_generation_browsertest.cc
@@ -67,7 +67,7 @@ // Tests that generating a MHTML does create contents. // Note that the actual content of the file is not tested, the purpose of this -// test is to ensure we were successfull in creating the MHTML data from the +// test is to ensure we were successful in creating the MHTML data from the // renderer. IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) { base::FilePath path(temp_dir_.path());
diff --git a/content/browser/fileapi/file_writer_delegate_unittest.cc b/content/browser/fileapi/file_writer_delegate_unittest.cc index c9bcfbb7..9eb73b1 100644 --- a/content/browser/fileapi/file_writer_delegate_unittest.cc +++ b/content/browser/fileapi/file_writer_delegate_unittest.cc
@@ -184,17 +184,15 @@ base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete, this)); } - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override { + int ReadRawData(net::IOBuffer* buf, int buf_size) override { if (remaining_bytes_ < buf_size) - buf_size = static_cast<int>(remaining_bytes_); + buf_size = remaining_bytes_; for (int i = 0; i < buf_size; ++i) buf->data()[i] = content_[cursor_++]; remaining_bytes_ -= buf_size; - SetStatus(net::URLRequestStatus()); - *bytes_read = buf_size; - return true; + return buf_size; } int GetResponseCode() const override { return 200; }
diff --git a/content/browser/geolocation/wifi_data_provider_linux.cc b/content/browser/geolocation/wifi_data_provider_linux.cc index 5fad8c58..29c9995 100644 --- a/content/browser/geolocation/wifi_data_provider_linux.cc +++ b/content/browser/geolocation/wifi_data_provider_linux.cc
@@ -170,7 +170,7 @@ ++fail_count; } } - // At least one successfull scan overrides any other adapter reporting error. + // At least one successful scan overrides any other adapter reporting error. return success_count || fail_count == 0; }
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc index 895044d71..10f507b 100644 --- a/content/browser/gpu/compositor_util.cc +++ b/content/browser/gpu/compositor_util.cc
@@ -240,9 +240,7 @@ return false; #if defined(OS_MACOSX) - // Disabled due to increased crash rates. - // http://crbug.com/554541 - return false; + return true; #else return false; #endif
diff --git a/content/browser/gpu/test_support_gpu.gypi b/content/browser/gpu/test_support_gpu.gypi index 7c4beaa..73f87eec 100644 --- a/content/browser/gpu/test_support_gpu.gypi +++ b/content/browser/gpu/test_support_gpu.gypi
@@ -25,13 +25,6 @@ 'include_dirs': [ '<(DEPTH)/third_party/wtl/include', ], - 'conditions': [ - ['win_use_allocator_shim==1', { - 'dependencies': [ - '../base/allocator/allocator.gyp:allocator', - ], - }], - ], 'configurations': { 'Debug': { 'msvs_settings': {
diff --git a/content/browser/histogram_message_filter.cc b/content/browser/histogram_message_filter.cc index a93a309..5c074a2 100644 --- a/content/browser/histogram_message_filter.cc +++ b/content/browser/histogram_message_filter.cc
@@ -8,7 +8,6 @@ #include "base/metrics/histogram.h" #include "base/metrics/statistics_recorder.h" #include "content/browser/histogram_controller.h" -#include "content/browser/tcmalloc_internals_request_job.h" #include "content/common/child_process_messages.h" #include "content/public/common/content_switches.h"
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index 52344e1..65db067 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -261,7 +261,7 @@ // List of blob files being newly written as part of this transaction. // These will be added to the primary blob journal prior to commit, then - // removed after a sucessful commit. + // removed after a successful commit. BlobJournalType blobs_to_write_; // List of blob files being deleted as part of this transaction. These will
diff --git a/content/browser/loader/resource_buffer.cc b/content/browser/loader/resource_buffer.cc index 58839db..9dc63d6 100644 --- a/content/browser/loader/resource_buffer.cc +++ b/content/browser/loader/resource_buffer.cc
@@ -54,11 +54,7 @@ min_alloc_size_ = min_allocation_size; max_alloc_size_ = max_allocation_size; -#if defined(OS_MACOSX) && !defined(OS_IOS) - return shared_mem_.CreateAndMapAnonymousMach(buf_size_); -#else return shared_mem_.CreateAndMapAnonymous(buf_size_); -#endif // defined(OS_MACOSX) && !defined(OS_IOS) } bool ResourceBuffer::IsInitialized() const {
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 391a6b413..f4b5fac 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -730,8 +730,8 @@ scoped_ptr<ResourceHandler> handler( new DownloadResourceHandler(id, request, started_cb, save_info.Pass())); if (delegate_) { - const ResourceRequestInfo* request_info( - ResourceRequestInfo::ForRequest(request)); + const ResourceRequestInfoImpl* request_info( + ResourceRequestInfoImpl::ForRequest(request)); ScopedVector<ResourceThrottle> throttles; delegate_->DownloadStarting( @@ -884,7 +884,7 @@ } void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) { - ResourceRequestInfo* info = loader->GetRequestInfo(); + ResourceRequestInfoImpl* info = loader->GetRequestInfo(); // Record final result of all resource loads. if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc index 5a9bbff..be19ccd 100644 --- a/content/browser/loader/resource_loader.cc +++ b/content/browser/loader/resource_loader.cc
@@ -312,19 +312,9 @@ bool fatal) { ResourceRequestInfoImpl* info = GetRequestInfo(); - int render_process_id; - int render_frame_id; - if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) - NOTREACHED(); - SSLManager::OnSSLCertificateError( - weak_ptr_factory_.GetWeakPtr(), - info->GetResourceType(), - request_->url(), - render_process_id, - render_frame_id, - ssl_info, - fatal); + weak_ptr_factory_.GetWeakPtr(), info->GetResourceType(), request_->url(), + info->GetWebContentsForRequest(), ssl_info, fatal); } void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
diff --git a/content/browser/loader/resource_request_info_impl.cc b/content/browser/loader/resource_request_info_impl.cc index 26f99f96..990ac79 100644 --- a/content/browser/loader/resource_request_info_impl.cc +++ b/content/browser/loader/resource_request_info_impl.cc
@@ -4,15 +4,34 @@ #include "content/browser/loader/resource_request_info_impl.h" +#include "base/command_line.h" +#include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/loader/global_routing_id.h" #include "content/browser/loader/resource_message_filter.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/net/url_request_user_data.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/global_request_id.h" +#include "content/public/common/content_switches.h" #include "content/public/common/process_type.h" #include "net/url_request/url_request.h" namespace content { +namespace { + +WebContents* GetWebContentsFromFTNID(int frame_tree_node_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + FrameTreeNode* frame_tree_node = + FrameTreeNode::GloballyFindByID(frame_tree_node_id); + if (!frame_tree_node) + return nullptr; + + return WebContentsImpl::FromFrameTreeNode(frame_tree_node); +} + +} // namespace + // ---------------------------------------------------------------------------- // ResourceRequestInfo @@ -168,6 +187,30 @@ ResourceRequestInfoImpl::~ResourceRequestInfoImpl() { } +base::Callback<WebContents*(void)> +ResourceRequestInfoImpl::GetWebContentsForRequest() const { + // PlzNavigate: navigation requests are created with a valid FrameTreeNode ID + // and invalid RenderProcessHost and RenderFrameHost IDs. The FrameTreeNode + // ID should be used to access the WebContents. + if (frame_tree_node_id_ != -1) { + DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBrowserSideNavigation)); + return base::Bind(&GetWebContentsFromFTNID, frame_tree_node_id_); + } + + // In other cases, use the RenderProcessHost ID + RenderFrameHost ID to get + // the WebContents. + int render_process_host_id = -1; + int render_frame_host_id = -1; + if (!GetAssociatedRenderFrame(&render_process_host_id, + &render_frame_host_id)) { + NOTREACHED(); + } + + return base::Bind(&WebContentsImpl::FromRenderFrameHostID, + render_process_host_id, render_frame_host_id); +} + ResourceContext* ResourceRequestInfoImpl::GetContext() const { return context_; } @@ -184,10 +227,6 @@ return origin_pid_; } -int ResourceRequestInfoImpl::GetRequestID() const { - return request_id_; -} - int ResourceRequestInfoImpl::GetRenderFrameID() const { return render_frame_id_; } @@ -273,6 +312,10 @@ } } +int ResourceRequestInfoImpl::GetRequestID() const { + return request_id_; +} + GlobalRequestID ResourceRequestInfoImpl::GetGlobalRequestID() const { return GlobalRequestID(child_id_, request_id_); }
diff --git a/content/browser/loader/resource_request_info_impl.h b/content/browser/loader/resource_request_info_impl.h index 40a597a3..db1f0a6 100644 --- a/content/browser/loader/resource_request_info_impl.h +++ b/content/browser/loader/resource_request_info_impl.h
@@ -23,6 +23,7 @@ class DetachableResourceHandler; class ResourceContext; class ResourceMessageFilter; +class WebContents; struct GlobalRequestID; struct GlobalRoutingID; @@ -74,7 +75,6 @@ int GetChildID() const override; int GetRouteID() const override; int GetOriginPID() const override; - int GetRequestID() const override; int GetRenderFrameID() const override; bool IsMainFrame() const override; bool ParentIsMainFrame() const override; @@ -93,8 +93,17 @@ bool IsUsingLoFi() const override; bool ShouldReportRawHeaders() const; + // Returns a callback that returns a pointer to the WebContents this request + // is associated with, or nullptr if it no longer exists or the request is + // not associated with a WebContents. The callback should only run on the UI + // thread. + // Note: Not all resource requests will be owned by a WebContents. For + // example, requests made by a ServiceWorker. + base::Callback<WebContents*(void)> GetWebContentsForRequest() const; + CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request); + CONTENT_EXPORT int GetRequestID() const; CONTENT_EXPORT GlobalRequestID GetGlobalRequestID() const; GlobalRoutingID GetGlobalRoutingID() const;
diff --git a/content/browser/mojo/mojo_shell_client_host.cc b/content/browser/mojo/mojo_shell_client_host.cc index 1bc85b5..3a1acdf 100644 --- a/content/browser/mojo/mojo_shell_client_host.cc +++ b/content/browser/mojo/mojo_shell_client_host.cc
@@ -4,14 +4,15 @@ #include "base/strings/stringprintf.h" #include "base/thread_task_runner_handle.h" +#include "components/mus/public/interfaces/gpu.mojom.h" #include "content/browser/mojo/mojo_shell_client_host.h" #include "content/common/mojo/mojo_messages.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/mojo_shell_connection.h" #include "ipc/ipc_sender.h" #include "mojo/application/public/cpp/application_impl.h" +#include "mojo/application/public/interfaces/application_manager.mojom.h" #include "mojo/converters/network/network_type_converters.h" -#include "mojo/shell/application_manager.mojom.h" #include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" #include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" @@ -82,8 +83,15 @@ // http://crbug.com/555393 std::string url = base::StringPrintf("exe:chrome_renderer%d", child_process_id); + + mojo::CapabilityFilterPtr filter(mojo::CapabilityFilter::New()); + mojo::Array<mojo::String> window_manager_interfaces; + window_manager_interfaces.push_back(mus::mojom::Gpu::Name_); + filter->filter.insert("mojo:mus", window_manager_interfaces.Pass()); application_manager->CreateInstanceForHandle( - mojo::ScopedHandle(mojo::Handle(handle.release().value())), url); + mojo::ScopedHandle(mojo::Handle(handle.release().value())), + url, + filter.Pass()); // Send the other end to the child via Chrome IPC. base::PlatformFile client_file = PlatformFileFromScopedPlatformHandle(
diff --git a/content/browser/net/view_http_cache_job_factory.cc b/content/browser/net/view_http_cache_job_factory.cc index 823ced9c..22b408e 100644 --- a/content/browser/net/view_http_cache_job_factory.cc +++ b/content/browser/net/view_http_cache_job_factory.cc
@@ -45,15 +45,8 @@ bool GetCharset(std::string* charset) override { return core_->GetCharset(charset); } - bool ReadRawData(net::IOBuffer* buf, - int buf_size, - int* out_bytes_read) override { - size_t bytes_read; - if (!core_->ReadRawData(buf, base::checked_cast<size_t>(buf_size), - &bytes_read)) - return false; - *out_bytes_read = base::checked_cast<int>(bytes_read); - return true; + int ReadRawData(net::IOBuffer* buf, int buf_size) override { + return core_->ReadRawData(buf, buf_size); } private: @@ -73,7 +66,7 @@ bool GetMimeType(std::string* mime_type) const; bool GetCharset(std::string* charset); - bool ReadRawData(net::IOBuffer* buf, size_t buf_size, size_t* bytes_read); + int ReadRawData(net::IOBuffer* buf, int buf_size); private: friend class base::RefCounted<Core>; @@ -172,18 +165,14 @@ return true; } -bool ViewHttpCacheJob::Core::ReadRawData(net::IOBuffer* buf, - size_t buf_size, - size_t* bytes_read) { - DCHECK(bytes_read); +int ViewHttpCacheJob::Core::ReadRawData(net::IOBuffer* buf, int buf_size) { DCHECK_LE(data_offset_, data_.size()); - size_t remaining = data_.size() - data_offset_; + int remaining = base::checked_cast<int>(data_.size() - data_offset_); if (buf_size > remaining) buf_size = remaining; memcpy(buf->data(), data_.data() + data_offset_, buf_size); data_offset_ += buf_size; - *bytes_read = buf_size; - return true; + return buf_size; } void ViewHttpCacheJob::Core::OnIOComplete(int result) {
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index fb9d0b7..eb14c85 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -150,7 +150,7 @@ // This LOG(INFO) deliberately exists to help track down the cause of // https://crbug.com/534537, where notifications sometimes do not react to // the user clicking on them. It should be removed once that's fixed. - LOG(INFO) << "Lookup for ServiceWoker Registration: sucesss:" << success + LOG(INFO) << "Lookup for ServiceWoker Registration: success:" << success << " action_index: " << action_index; #endif if (!success) {
diff --git a/content/browser/power_save_blocker_x11.cc b/content/browser/power_save_blocker_x11.cc index ef2acd1..4783063 100644 --- a/content/browser/power_save_blocker_x11.cc +++ b/content/browser/power_save_blocker_x11.cc
@@ -89,12 +89,12 @@ // Apply or remove the power save block, respectively. These methods should be // called once each, on the same thread, per instance. They block waiting for // the action to complete (with a timeout); the thread must thus allow I/O. - void ApplyBlock(DBusAPI api); - void RemoveBlock(DBusAPI api); + void ApplyBlock(); + void RemoveBlock(); // Asynchronous callback functions for ApplyBlock and RemoveBlock. // Functions do not receive ownership of |response|. - void ApplyBlockFinished(DBusAPI api, dbus::Response* response); + void ApplyBlockFinished(dbus::Response* response); void RemoveBlockFinished(dbus::Response* response); // If DPMS (the power saving system in X11) is not enabled, then we don't want @@ -132,7 +132,7 @@ // The cookie that identifies our inhibit request, // or 0 if there is no active inhibit request. - uint32 inhibit_cookie_; + uint32_t inhibit_cookie_; DISALLOW_COPY_AND_ASSIGN(Delegate); }; @@ -168,7 +168,7 @@ enqueue_apply_ = false; } else if (api_ != NO_API) { BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&Delegate::RemoveBlock, this, api_)); + base::Bind(&Delegate::RemoveBlock, this)); } } @@ -181,12 +181,12 @@ // library, so we need to use the same thread above for RemoveBlock(). It // must be a thread that allows I/O operations, so we use the FILE thread. BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&Delegate::ApplyBlock, this, api_)); + base::Bind(&Delegate::ApplyBlock, this)); } enqueue_apply_ = false; } -void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) { +void PowerSaveBlockerImpl::Delegate::ApplyBlock() { DCHECK_CURRENTLY_ON(BrowserThread::FILE); DCHECK(!bus_); // ApplyBlock() should only be called once. DCHECK(!block_inflight_); @@ -200,7 +200,7 @@ scoped_ptr<dbus::MethodCall> method_call; scoped_ptr<dbus::MessageWriter> message_writer; - switch (api) { + switch (api_) { case NO_API: NOTREACHED(); // We should never call this method with this value. return; @@ -221,7 +221,7 @@ message_writer->AppendUint32(0); // should be toplevel_xid message_writer->AppendString(description_); { - uint32 flags = 0; + uint32_t flags = 0; switch (type_) { case kPowerSaveBlockPreventDisplaySleep: flags |= INHIBIT_MARK_SESSION_IDLE; @@ -253,12 +253,10 @@ block_inflight_ = true; object_proxy->CallMethod( method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this, - api)); + base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this)); } void PowerSaveBlockerImpl::Delegate::ApplyBlockFinished( - DBusAPI api, dbus::Response* response) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); DCHECK(bus_); @@ -281,11 +279,11 @@ // RemoveBlock() was called while the Inhibit operation was in flight, // so go ahead and remove the block now. BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&Delegate::RemoveBlock, this, api_)); + base::Bind(&Delegate::RemoveBlock, this)); } } -void PowerSaveBlockerImpl::Delegate::RemoveBlock(DBusAPI api) { +void PowerSaveBlockerImpl::Delegate::RemoveBlock() { DCHECK_CURRENTLY_ON(BrowserThread::FILE); DCHECK(bus_); // RemoveBlock() should only be called once. DCHECK(!unblock_inflight_); @@ -301,7 +299,7 @@ scoped_refptr<dbus::ObjectProxy> object_proxy; scoped_ptr<dbus::MethodCall> method_call; - switch (api) { + switch (api_) { case NO_API: NOTREACHED(); // We should never call this method with this value. return; @@ -342,11 +340,12 @@ inhibit_cookie_ = 0; bus_->ShutdownAndBlock(); - bus_ = NULL; + bus_ = nullptr; } // static bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); XDisplay* display = gfx::GetXDisplay(); BOOL enabled = false; int dummy; @@ -359,6 +358,7 @@ // static DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_ptr<base::Environment> env(base::Environment::Create()); switch (base::nix::GetDesktopEnvironment(env.get())) { case base::nix::DESKTOP_ENVIRONMENT_GNOME:
diff --git a/content/browser/profiler_message_filter.cc b/content/browser/profiler_message_filter.cc index 4bd85e21..0b7acf0 100644 --- a/content/browser/profiler_message_filter.cc +++ b/content/browser/profiler_message_filter.cc
@@ -6,7 +6,6 @@ #include "base/tracked_objects.h" #include "content/browser/profiler_controller_impl.h" -#include "content/browser/tcmalloc_internals_request_job.h" #include "content/common/child_process_messages.h" namespace content { @@ -26,9 +25,6 @@ IPC_BEGIN_MESSAGE_MAP(ProfilerMessageFilter, message) IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ChildProfilerData, OnChildProfilerData) -#if defined(USE_TCMALLOC) - IPC_MESSAGE_HANDLER(ChildProcessHostMsg_TcmallocStats, OnTcmallocStats) -#endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -43,11 +39,4 @@ sequence_number, profiler_data, process_type_); } -#if defined(USE_TCMALLOC) -void ProfilerMessageFilter::OnTcmallocStats(const std::string& output) { - AboutTcmallocOutputs::GetInstance()->OnStatsForChildProcess( - peer_pid(), process_type_, output); -} -#endif - }
diff --git a/content/browser/profiler_message_filter.h b/content/browser/profiler_message_filter.h index 875e45d..2b2d6a6 100644 --- a/content/browser/profiler_message_filter.h +++ b/content/browser/profiler_message_filter.h
@@ -36,10 +36,6 @@ int sequence_number, const tracked_objects::ProcessDataSnapshot& profiler_data); -#if defined(USE_TCMALLOC) - void OnTcmallocStats(const std::string& output); -#endif - content::ProcessType process_type_; DISALLOW_COPY_AND_ASSIGN(ProfilerMessageFilter);
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 7db4d7a..3f2ee64 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -445,8 +445,8 @@ command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); settings.initial_debug_state.show_fps_counter = command_line->HasSwitch(cc::switches::kUIShowFPSCounter); - if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees)) - settings.use_property_trees = false; + settings.use_property_trees = + command_line->HasSwitch(cc::switches::kEnableCompositorPropertyTrees); // TODO(enne): Update this this compositor to use the scheduler. settings.single_thread_proxy_scheduler = false;
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/content/browser/renderer_host/media/video_capture_buffer_pool.cc index 76cc9b6b..0d664285 100644 --- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc +++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -6,7 +6,6 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" #include "base/stl_util.h" #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" #include "content/public/browser/browser_thread.h" @@ -65,7 +64,8 @@ : public VideoCaptureBufferPool::BufferHandle { public: GpuMemoryBufferBufferHandle(const gfx::Size& dimensions, - ScopedVector<gfx::GpuMemoryBuffer>* gmbs) + std::vector< + scoped_ptr<gfx::GpuMemoryBuffer>>* gmbs) : dimensions_(dimensions), gmbs_(gmbs) { DCHECK(gmbs); } @@ -93,7 +93,7 @@ private: const gfx::Size dimensions_; - ScopedVector<gfx::GpuMemoryBuffer>* const gmbs_; + std::vector<scoped_ptr<gfx::GpuMemoryBuffer>>* const gmbs_; }; // Tracker specifics for SharedMemory. @@ -155,7 +155,7 @@ private: gfx::Size dimensions_; // Owned references to GpuMemoryBuffers. - ScopedVector<gfx::GpuMemoryBuffer> gpu_memory_buffers_; + std::vector<scoped_ptr<gfx::GpuMemoryBuffer>> gpu_memory_buffers_; }; VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker() : Tracker() {}
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.cc b/content/browser/renderer_host/p2p/socket_host_tcp.cc index 0273b646c..cb4d60d 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.cc +++ b/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -167,7 +167,7 @@ } else { // If we are not doing TLS, we are ready to send data now. // In case of TLS, SignalConnect will be sent only after TLS handshake is - // successfull. So no buffering will be done at socket handlers if any + // successful. So no buffering will be done at socket handlers if any // packets sent before that by the application. OnOpen(); }
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 48f8e3f..3ffdc89d 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc
@@ -149,8 +149,6 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message) - IPC_MESSAGE_HANDLER(RenderProcessHostMsg_GetProcessMemorySizes, - OnGetProcessMemorySizes) IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnCreateWindow) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnCreateWidget) @@ -291,24 +289,6 @@ render_widget_helper_->CreateNewFullscreenWidget(opener_id, route_id); } -void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes, - size_t* shared_bytes) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - using base::ProcessMetrics; -#if !defined(OS_MACOSX) || defined(OS_IOS) - scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics( - PeerHandle())); -#else - scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics( - PeerHandle(), BrowserChildProcessHost::GetPortProvider())); -#endif - if (!metrics->GetMemoryBytes(private_bytes, shared_bytes)) { - *private_bytes = 0; - *shared_bytes = 0; - } -} - - void RenderMessageFilter::OnGenerateRoutingID(int* route_id) { *route_id = render_widget_helper_->GetNextRoutingID(); }
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 5668d50d..a218c53 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -166,6 +166,7 @@ #include "storage/browser/fileapi/sandbox_file_system_backend.h" #include "third_party/icu/source/common/unicode/unistr.h" #include "third_party/icu/source/i18n/unicode/timezone.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/ui_base_switches.h" #include "ui/events/event_switches.h" @@ -1421,10 +1422,10 @@ // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc. cc::switches::kDisableCachedPictureRaster, cc::switches::kDisableCompositedAntialiasing, - cc::switches::kDisableCompositorPropertyTrees, cc::switches::kDisableMainFrameBeforeActivation, cc::switches::kDisableThreadedAnimation, cc::switches::kEnableBeginFrameScheduling, + cc::switches::kEnableCompositorPropertyTrees, cc::switches::kEnableGpuBenchmarking, cc::switches::kEnableMainFrameBeforeActivation, cc::switches::kShowCompositedLayerBorders, @@ -2443,6 +2444,16 @@ RegisterChildWithExternalShell(id_, GetHandle(), this); #endif +#if defined(OS_WIN) + if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk") && + child_process_launcher_.get()) { + HANDLE process_handle = child_process_launcher_->GetProcess().Handle(); + HANDLE client_pipe = mojo::embedder::ChildProcessLaunched(process_handle); + Send(new ChildProcessMsg_SetMojoParentPipeHandle( + IPC::GetFileHandleForProcess(client_pipe, process_handle, true))); + } +#endif + // Allow Mojo to be setup before the renderer sees any Chrome IPC messages. // This way, Mojo can be safely used from the renderer in response to any // Chrome IPC message.
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index 61c2feb..b4e4169 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -39,6 +39,9 @@ // of the RenderWidgetHost. class CONTENT_EXPORT RenderWidgetHostDelegate { public: + // The RenderWidgetHost has just been created. + virtual void RenderWidgetCreated(RenderWidgetHostImpl* render_widget_host) {} + // The RenderWidgetHost is going to be deleted. virtual void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) {}
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 14633dc..36c9768 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -245,6 +245,8 @@ new_content_rendering_timeout_.reset(new TimeoutMonitor( base::Bind(&RenderWidgetHostImpl::ClearDisplayedGraphics, weak_factory_.GetWeakPtr()))); + + delegate_->RenderWidgetCreated(this); } RenderWidgetHostImpl::~RenderWidgetHostImpl() {
diff --git a/content/browser/renderer_host/websocket_host.cc b/content/browser/renderer_host/websocket_host.cc index 70c846e3..8c04e04 100644 --- a/content/browser/renderer_host/websocket_host.cc +++ b/content/browser/renderer_host/websocket_host.cc
@@ -14,6 +14,7 @@ #include "content/browser/ssl/ssl_error_handler.h" #include "content/browser/ssl/ssl_manager.h" #include "content/common/websocket_messages.h" +#include "content/public/browser/render_frame_host.h" #include "ipc/ipc_message_macros.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" @@ -274,13 +275,9 @@ << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal; ssl_error_handler_delegate_.reset( new SSLErrorHandlerDelegate(callbacks.Pass())); - SSLManager::OnSSLCertificateError(ssl_error_handler_delegate_->GetWeakPtr(), - RESOURCE_TYPE_SUB_RESOURCE, - url, - dispatcher_->render_process_id(), - render_frame_id_, - ssl_info, - fatal); + SSLManager::OnSSLCertificateSubresourceError( + ssl_error_handler_delegate_->GetWeakPtr(), url, + dispatcher_->render_process_id(), render_frame_id_, ssl_info, fatal); // The above method is always asynchronous. return WebSocketEventInterface::CHANNEL_ALIVE; }
diff --git a/content/browser/safe_util_win.h b/content/browser/safe_util_win.h index a668e95..ce044c7 100644 --- a/content/browser/safe_util_win.h +++ b/content/browser/safe_util_win.h
@@ -23,7 +23,7 @@ // // If Attachment Execution Services is unavailable, then this function will // attempt to manually annotate the file with security zone information. A -// failure code will be returned in this case even if the file is sucessfully +// failure code will be returned in this case even if the file is successfully // annotated. // // IAE::Save() will delete the file if it was found to be blocked by local
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 93579911..6aa92af8 100644 --- a/content/browser/service_worker/service_worker_read_from_cache_job.cc +++ b/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -41,26 +41,9 @@ } void ServiceWorkerReadFromCacheJob::Start() { - TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", - "ServiceWorkerReadFromCacheJob::ReadInfo", this, - "URL", request_->url().spec()); - if (!context_) { - NotifyStartError( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); - return; - } - - // Create a response reader and start reading the headers, - // we'll continue when thats done. - if (is_main_script()) - version_->embedded_worker()->OnScriptReadStarted(); - reader_ = context_->storage()->CreateResponseReader(resource_id_); - http_info_io_buffer_ = new HttpResponseInfoIOBuffer; - reader_->ReadInfo( - http_info_io_buffer_.get(), - base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete, - weak_factory_.GetWeakPtr())); - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ServiceWorkerReadFromCacheJob::StartAsync, + weak_factory_.GetWeakPtr())); } void ServiceWorkerReadFromCacheJob::Kill() { @@ -122,11 +105,9 @@ range_requested_ = ranges[0]; } -bool ServiceWorkerReadFromCacheJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int ServiceWorkerReadFromCacheJob::ReadRawData(net::IOBuffer* buf, + int buf_size) { DCHECK_NE(buf_size, 0); - DCHECK(bytes_read); DCHECK(!reader_->IsReadPending()); TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerReadFromCacheJob::ReadRawData", @@ -135,8 +116,31 @@ reader_->ReadData(buf, buf_size, base::Bind(&ServiceWorkerReadFromCacheJob::OnReadComplete, weak_factory_.GetWeakPtr())); + return net::ERR_IO_PENDING; +} + +void ServiceWorkerReadFromCacheJob::StartAsync() { + TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", + "ServiceWorkerReadFromCacheJob::ReadInfo", this, + "URL", request_->url().spec()); + if (!context_) { + // NotifyStartError is not safe to call synchronously in Start. + NotifyStartError( + net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); + return; + } + + // Create a response reader and start reading the headers, + // we'll continue when thats done. + if (is_main_script()) + version_->embedded_worker()->OnScriptReadStarted(); + reader_ = context_->storage()->CreateResponseReader(resource_id_); + http_info_io_buffer_ = new HttpResponseInfoIOBuffer; + reader_->ReadInfo( + http_info_io_buffer_.get(), + base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete, + weak_factory_.GetWeakPtr())); SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; } const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const { @@ -154,6 +158,8 @@ ServiceWorkerMetrics::CountReadResponseResult( ServiceWorkerMetrics::READ_HEADERS_ERROR); Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + NotifyStartError( + net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); return; } DCHECK_GE(result, 0); @@ -207,23 +213,22 @@ } if (is_main_script()) version_->embedded_worker()->OnScriptReadFinished(); - NotifyDone(status); } void ServiceWorkerReadFromCacheJob::OnReadComplete(int result) { ServiceWorkerMetrics::ReadResponseResult check_result; - if (result == 0) { + + if (result >= 0) { check_result = ServiceWorkerMetrics::READ_OK; - Done(net::URLRequestStatus()); - } else if (result < 0) { + if (result == 0) + Done(net::URLRequestStatus()); + } else { check_result = ServiceWorkerMetrics::READ_DATA_ERROR; Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); - } else { - check_result = ServiceWorkerMetrics::READ_OK; - SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status } + ServiceWorkerMetrics::CountReadResponseResult(check_result); - NotifyReadComplete(result); + ReadRawDataComplete(result); TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerReadFromCacheJob::ReadRawData", this,
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.h b/content/browser/service_worker/service_worker_read_from_cache_job.h index fccde7a..a62893d 100644 --- a/content/browser/service_worker/service_worker_read_from_cache_job.h +++ b/content/browser/service_worker/service_worker_read_from_cache_job.h
@@ -51,13 +51,14 @@ void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; // Reader completion callbacks. void OnReadInfoComplete(int result); void OnReadComplete(int result); // Helpers + void StartAsync(); const net::HttpResponseInfo* http_info() const; bool is_range_request() const { return range_requested_.IsValid(); } void SetupRangeResponse(int response_data_size);
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc index 15c85a1..143e354 100644 --- a/content/browser/service_worker/service_worker_url_request_job.cc +++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -203,50 +203,44 @@ byte_range_ = ranges[0]; } -bool ServiceWorkerURLRequestJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int ServiceWorkerURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { DCHECK(buf); DCHECK_GE(buf_size, 0); - DCHECK(bytes_read); DCHECK(waiting_stream_url_.is_empty()); + + int bytes_read = 0; + if (stream_.get()) { - switch (stream_->ReadRawData(buf, buf_size, bytes_read)) { + switch (stream_->ReadRawData(buf, buf_size, &bytes_read)) { case Stream::STREAM_HAS_DATA: - DCHECK_GT(*bytes_read, 0); - return true; + DCHECK_GT(bytes_read, 0); + return bytes_read; case Stream::STREAM_COMPLETE: - DCHECK(!*bytes_read); + DCHECK_EQ(0, bytes_read); RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE); - return true; + return 0; case Stream::STREAM_EMPTY: stream_pending_buffer_ = buf; stream_pending_buffer_size_ = buf_size; - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; + return net::ERR_IO_PENDING; case Stream::STREAM_ABORTED: // Handle this as connection reset. RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED); - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_CONNECTION_RESET)); - return false; + return net::ERR_CONNECTION_RESET; } NOTREACHED(); - return false; + return net::ERR_FAILED; } - if (!blob_request_) { - *bytes_read = 0; - return true; - } - blob_request_->Read(buf, buf_size, bytes_read); + if (!blob_request_) + return 0; + blob_request_->Read(buf, buf_size, &bytes_read); net::URLRequestStatus status = blob_request_->status(); - SetStatus(status); - if (status.is_io_pending()) - return false; - if (status.is_success() && *bytes_read == 0) + if (status.status() != net::URLRequestStatus::SUCCESS) + return status.error(); + if (bytes_read == 0) RecordResult(ServiceWorkerMetrics::REQUEST_JOB_BLOB_RESPONSE); - return status.is_success(); + return bytes_read; } // TODO(falken): Refactor Blob and Stream specific handling to separate classes. @@ -292,29 +286,18 @@ void ServiceWorkerURLRequestJob::OnReadCompleted(net::URLRequest* request, int bytes_read) { - SetStatus(request->status()); if (!request->status().is_success()) { RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_BLOB_READ); - NotifyDone(request->status()); - return; - } - - if (bytes_read == 0) { - // Protect because NotifyReadComplete() can destroy |this|. - scoped_refptr<ServiceWorkerURLRequestJob> protect(this); + } else if (bytes_read == 0) { RecordResult(ServiceWorkerMetrics::REQUEST_JOB_BLOB_RESPONSE); - NotifyReadComplete(bytes_read); - NotifyDone(request->status()); - return; } - NotifyReadComplete(bytes_read); + net::URLRequestStatus status = request->status(); + ReadRawDataComplete(status.is_success() ? bytes_read : status.error()); } // Overrides for Stream reading ----------------------------------------------- void ServiceWorkerURLRequestJob::OnDataAvailable(Stream* stream) { - // Clear the IO_PENDING status. - SetStatus(net::URLRequestStatus()); // Do nothing if stream_pending_buffer_ is empty, i.e. there's no ReadRawData // operation waiting for IO completion. if (!stream_pending_buffer_.get()) @@ -323,15 +306,15 @@ // stream_pending_buffer_ is set to the IOBuffer instance provided to // ReadRawData() by URLRequestJob. - int bytes_read = 0; + int result = 0; switch (stream_->ReadRawData(stream_pending_buffer_.get(), - stream_pending_buffer_size_, &bytes_read)) { + stream_pending_buffer_size_, &result)) { case Stream::STREAM_HAS_DATA: - DCHECK_GT(bytes_read, 0); + DCHECK_GT(result, 0); break; case Stream::STREAM_COMPLETE: // Calling NotifyReadComplete with 0 signals completion. - DCHECK(!bytes_read); + DCHECK(!result); RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE); break; case Stream::STREAM_EMPTY: @@ -339,9 +322,8 @@ break; case Stream::STREAM_ABORTED: // Handle this as connection reset. + result = net::ERR_CONNECTION_RESET; RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_STREAM_ABORTED); - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_CONNECTION_RESET)); break; } @@ -349,7 +331,7 @@ // safe for the observer to read. stream_pending_buffer_ = nullptr; stream_pending_buffer_size_ = 0; - NotifyReadComplete(bytes_read); + ReadRawDataComplete(result); } void ServiceWorkerURLRequestJob::OnStreamRegistered(Stream* stream) { @@ -645,7 +627,7 @@ // error. if (response.status_code == 0) { RecordStatusZeroResponseError(response.error); - NotifyDone( + NotifyStartError( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); return; }
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h index 4815c0b..2a50c94 100644 --- a/content/browser/service_worker/service_worker_url_request_job.h +++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -87,7 +87,7 @@ void GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override; int GetResponseCode() const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; // net::URLRequest::Delegate overrides that read the blob from the // ServiceWorkerFetchResponse.
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.cc b/content/browser/service_worker/service_worker_write_to_cache_job.cc index 24bcd0f4..ba605c06 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job.cc +++ b/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/strings/stringprintf.h" +#include "base/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "content/browser/service_worker/service_worker_cache_writer.h" #include "content/browser/service_worker/service_worker_context_core.h" @@ -47,7 +48,7 @@ // developers. // TODO(falken): Redesign this class so we don't have to fail at the network // stack layer just to cancel the update. -const int kIdenticalScriptError = net::ERR_FILE_EXISTS; +const net::Error kIdenticalScriptError = net::ERR_FILE_EXISTS; } // namespace @@ -79,11 +80,18 @@ } void ServiceWorkerWriteToCacheJob::Start() { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ServiceWorkerWriteToCacheJob::StartAsync, + weak_factory_.GetWeakPtr())); +} + +void ServiceWorkerWriteToCacheJob::StartAsync() { TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerWriteToCacheJob::ExecutingJob", this, "URL", request_->url().spec()); if (!context_) { + // NotifyStartError is not safe to call synchronously in Start(). NotifyStartError( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); return; @@ -108,8 +116,9 @@ has_been_killed_ = true; net_request_.reset(); if (did_notify_started_) { - NotifyFinishedCaching(net::URLRequestStatus::FromError(net::ERR_ABORTED), - kKilledError); + net::Error error = NotifyFinishedCaching( + net::URLRequestStatus::FromError(net::ERR_ABORTED), kKilledError); + DCHECK_EQ(net::ERR_ABORTED, error); } writer_.reset(); context_.reset(); @@ -156,40 +165,20 @@ net_request_->SetExtraRequestHeaders(headers); } -bool ServiceWorkerWriteToCacheJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { - net::URLRequestStatus status = ReadNetData(buf, buf_size, bytes_read); - SetStatus(status); +int ServiceWorkerWriteToCacheJob::ReadRawData(net::IOBuffer* buf, + int buf_size) { + int bytes_read = 0; + net::URLRequestStatus status = ReadNetData(buf, buf_size, &bytes_read); if (status.is_io_pending()) - return false; + return net::ERR_IO_PENDING; if (!status.is_success()) { - NotifyDoneHelper(status, kFetchScriptError); - return false; + net::Error error = NotifyFinishedCaching(status, kFetchScriptError); + DCHECK_EQ(status.error(), error); + return error; } - HandleNetData(*bytes_read); - status = GetStatus(); - - // Synchronous EOFs that do not replace the incumbent entry are considered - // failures. Since normally the URLRequestJob's status would be set by - // ReadNetData or HandleNetData, this code has to manually fix up the status - // to match the failure this function is about to return. - if (status.status() == net::URLRequestStatus::SUCCESS && *bytes_read == 0 && - !cache_writer_->did_replace()) { - status = net::URLRequestStatus::FromError(kIdenticalScriptError); - } - - if (!status.is_success()) { - NotifyDoneHelper(status, ""); - return false; - } - - // Since URLRequestStatus::is_success() means "SUCCESS or IO_PENDING", but the - // contract of this function is "return true for synchronous successes only", - // it is important to test against SUCCESS explicitly here. - return status.status() == net::URLRequestStatus::SUCCESS; + return HandleNetData(bytes_read); } const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const { @@ -244,9 +233,9 @@ TRACE_EVENT0("ServiceWorker", "ServiceWorkerWriteToCacheJob::OnReceivedRedirect"); // Script resources can't redirect. - NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_UNSAFE_REDIRECT), - kRedirectError); + NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_UNSAFE_REDIRECT), + kRedirectError); } void ServiceWorkerWriteToCacheJob::OnAuthRequired( @@ -256,7 +245,7 @@ TRACE_EVENT0("ServiceWorker", "ServiceWorkerWriteToCacheJob::OnAuthRequired"); // TODO(michaeln): Pass this thru to our jobs client. - NotifyDoneHelper( + NotifyStartErrorHelper( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), kClientAuthenticationError); } @@ -269,7 +258,7 @@ "ServiceWorkerWriteToCacheJob::OnCertificateRequested"); // TODO(michaeln): Pass this thru to our jobs client. // see NotifyCertificateRequested. - NotifyDoneHelper( + NotifyStartErrorHelper( net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED), kClientAuthenticationError); } @@ -283,9 +272,9 @@ "ServiceWorkerWriteToCacheJob::OnSSLCertificateError"); // TODO(michaeln): Pass this thru to our jobs client, // see NotifySSLCertificateError. - NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - kSSLError); + NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + kSSLError); } void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart( @@ -301,15 +290,15 @@ net::URLRequest* request) { DCHECK_EQ(net_request_.get(), request); if (!request->status().is_success()) { - NotifyDoneHelper(request->status(), kFetchScriptError); + NotifyStartErrorHelper(request->status(), kFetchScriptError); return; } if (request->GetResponseCode() / 100 != 2) { std::string error_message = base::StringPrintf(kBadHTTPResponseError, request->GetResponseCode()); - NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INVALID_RESPONSE), - error_message); + NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INVALID_RESPONSE), + error_message); // TODO(michaeln): Instead of error'ing immediately, send the net // response to our consumer, just don't cache it? return; @@ -320,9 +309,10 @@ const net::HttpNetworkSession::Params* session_params = request->context()->GetNetworkSessionParams(); if (!session_params || !session_params->ignore_certificate_errors) { - NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - kSSLError); + NotifyStartErrorHelper( + net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + kSSLError); return; } } @@ -337,9 +327,10 @@ mime_type.empty() ? kNoMIMEError : base::StringPrintf(kBadMIMEError, mime_type.c_str()); - NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - error_message); + NotifyStartErrorHelper( + net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + error_message); return; } @@ -375,52 +366,31 @@ NotifyHeadersComplete(); } -void ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) { - io_buffer_bytes_ = bytes_read; - net::Error error = cache_writer_->MaybeWriteData( - io_buffer_.get(), bytes_read, - base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete, - weak_factory_.GetWeakPtr())); - SetStatus(net::URLRequestStatus::FromError(error)); - - // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete. - if (error != net::ERR_IO_PENDING && bytes_read == 0) { - NotifyFinishedCaching(net::URLRequestStatus::FromError(error), - std::string()); - } -} - void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) { SetStatus(net::URLRequestStatus::FromError(error)); DCHECK_NE(net::ERR_IO_PENDING, error); - if (io_buffer_bytes_ == 0) { - NotifyDoneHelper(net::URLRequestStatus::FromError(error), std::string()); - } - NotifyReadComplete(error == net::OK ? io_buffer_bytes_ : error); + if (io_buffer_bytes_ == 0) + error = NotifyFinishedCaching(net::URLRequestStatus::FromError(error), ""); + ReadRawDataComplete(error == net::OK ? io_buffer_bytes_ : error); } void ServiceWorkerWriteToCacheJob::OnReadCompleted(net::URLRequest* request, int bytes_read) { DCHECK_EQ(net_request_.get(), request); + + int result; if (bytes_read < 0) { DCHECK(!request->status().is_success()); - NotifyDoneHelper(request->status(), kFetchScriptError); + result = NotifyFinishedCaching(request->status(), kFetchScriptError); + } else { + result = HandleNetData(bytes_read); + } + + // ReadRawDataComplete will be called in OnWriteDataComplete, so return early. + if (result == net::ERR_IO_PENDING) return; - } - HandleNetData(bytes_read); - // HandleNetData can cause status of this job to change. If the status changes - // to IO_PENDING, that means HandleNetData has pending IO, and - // NotifyReadComplete will be called later by the appropriate callback. - if (!GetStatus().is_io_pending()) { - int result = GetStatus().status() == net::URLRequestStatus::SUCCESS - ? bytes_read - : GetStatus().error(); - // If bytes_read is 0, HandleNetData synchronously completed and this job is - // at EOF. - if (bytes_read == 0) - NotifyDoneHelper(GetStatus(), std::string()); - NotifyReadComplete(result); - } + + ReadRawDataComplete(result); } bool ServiceWorkerWriteToCacheJob::CheckPathRestriction( @@ -434,43 +404,57 @@ if (!ServiceWorkerUtils::IsPathRestrictionSatisfied( version_->scope(), url_, has_header ? &service_worker_allowed : nullptr, &error_message)) { - NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_INSECURE_RESPONSE), - error_message); + NotifyStartErrorHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED, + net::ERR_INSECURE_RESPONSE), + error_message); return false; } return true; } -void ServiceWorkerWriteToCacheJob::NotifyDoneHelper( +int ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) { + io_buffer_bytes_ = bytes_read; + net::Error error = cache_writer_->MaybeWriteData( + io_buffer_.get(), bytes_read, + base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete, + weak_factory_.GetWeakPtr())); + + // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete. + if (error != net::ERR_IO_PENDING && bytes_read == 0) { + error = NotifyFinishedCaching(net::URLRequestStatus::FromError(error), + std::string()); + } + return error == net::OK ? bytes_read : error; +} + +void ServiceWorkerWriteToCacheJob::NotifyStartErrorHelper( const net::URLRequestStatus& status, const std::string& status_message) { DCHECK(!status.is_io_pending()); - // Note that NotifyFinishedCaching has logic in it to detect the special case - // mentioned below as well. - NotifyFinishedCaching(status, status_message); + net::Error error = NotifyFinishedCaching(status, status_message); + // The special case mentioned in NotifyFinishedCaching about script being + // identical does not apply here, since the entire body needs to be read + // before this is relevant. + DCHECK_EQ(status.error(), error); net::URLRequestStatus reported_status = status; std::string reported_status_message = status_message; - // A strange special case: requests that successfully fetch the entire - // ServiceWorker and write it back, but which did not replace the incumbent - // script because the new script was identical, are considered to have failed. - if (status.is_success() && !cache_writer_->did_replace()) { - reported_status = net::URLRequestStatus::FromError(kIdenticalScriptError); - reported_status_message = ""; - } - SetStatus(reported_status); - NotifyDone(reported_status); + NotifyStartError(reported_status); } -void ServiceWorkerWriteToCacheJob::NotifyFinishedCaching( +net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching( net::URLRequestStatus status, const std::string& status_message) { + net::Error result = static_cast<net::Error>(status.error()); if (did_notify_finished_) - return; + return result; + + int size = -1; + if (status.is_success()) + size = cache_writer_->bytes_written(); // If all the calls to MaybeWriteHeaders/MaybeWriteData succeeded, but the // incumbent entry wasn't actually replaced because the new entry was @@ -478,17 +462,18 @@ // exists. if (status.status() == net::URLRequestStatus::SUCCESS && !cache_writer_->did_replace()) { - status = net::URLRequestStatus::FromError(kIdenticalScriptError); + result = kIdenticalScriptError; + status = net::URLRequestStatus::FromError(result); version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS); + version_->script_cache_map()->NotifyFinishedCaching(url_, size, status, + std::string()); + } else { + version_->script_cache_map()->NotifyFinishedCaching(url_, size, status, + status_message); } - int size = -1; - if (status.is_success()) - size = cache_writer_->bytes_written(); - - version_->script_cache_map()->NotifyFinishedCaching(url_, size, status, - status_message); did_notify_finished_ = true; + return result; } scoped_ptr<ServiceWorkerResponseReader>
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.h b/content/browser/service_worker/service_worker_write_to_cache_job.h index 92272399..e614912 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job.h +++ b/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -64,6 +64,7 @@ // net::URLRequestJob overrides void Start() override; + void StartAsync(); void Kill() override; net::LoadState GetLoadState() const override; bool GetCharset(std::string* charset) override; @@ -71,7 +72,7 @@ void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; const net::HttpResponseInfo* http_info() const; @@ -109,18 +110,22 @@ bool CheckPathRestriction(net::URLRequest* request); // Writes network data back to the script cache if needed, and notifies the - // script cache of fetch completion at EOF. This function might need to do - // asynchronous IO; if so, it signals this through setting the URLRequestJob's - // status to IO_PENDING. After this function returns, if the URLRequestJob - // isn't IO_PENDING, all of the data in |io_buffer_| has been written back to - // the script cache if necessary. - void HandleNetData(int bytes_read); + // script cache of fetch completion at EOF. This function returns + // net::IO_PENDING if the IO is to be completed asynchronously, returns a + // negative number that represents a corresponding net error code (other than + // net::IO_PENDING) if an error occurred, or returns a non-negative number + // that represents the number of network bytes read. If the return value is + // non-negative, all of the data in |io_buffer_| has been written back to the + // script cache if necessary. + int HandleNetData(int bytes_read); - void NotifyDoneHelper(const net::URLRequestStatus& status, - const std::string& status_message); + void NotifyStartErrorHelper(const net::URLRequestStatus& status, + const std::string& status_message); - void NotifyFinishedCaching(net::URLRequestStatus status, - const std::string& status_message); + // Returns an error code that is passed in through |status| or a new one if an + // additional error is found. + net::Error NotifyFinishedCaching(net::URLRequestStatus status, + const std::string& status_message); scoped_ptr<ServiceWorkerResponseReader> CreateCacheResponseReader(); scoped_ptr<ServiceWorkerResponseWriter> CreateCacheResponseWriter(); @@ -140,6 +145,7 @@ bool has_been_killed_; bool did_notify_started_; bool did_notify_finished_; + base::WeakPtrFactory<ServiceWorkerWriteToCacheJob> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerWriteToCacheJob);
diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc index 221c1dd..af5b65d 100644 --- a/content/browser/shared_worker/shared_worker_service_impl.cc +++ b/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -447,9 +447,8 @@ } std::vector<int> remove_pending_instance_list; - for (PendingInstaneMap::iterator iter = pending_instances_.begin(); - iter != pending_instances_.end(); - ++iter) { + for (PendingInstanceMap::iterator iter = pending_instances_.begin(); + iter != pending_instances_.end(); ++iter) { iter->second->RemoveRequest(filter->render_process_id()); if (!iter->second->requests()->size()) remove_pending_instance_list.push_back(iter->first); @@ -616,9 +615,8 @@ SharedWorkerServiceImpl::SharedWorkerPendingInstance* SharedWorkerServiceImpl::FindPendingInstance( const SharedWorkerInstance& instance) { - for (PendingInstaneMap::iterator iter = pending_instances_.begin(); - iter != pending_instances_.end(); - ++iter) { + for (PendingInstanceMap::iterator iter = pending_instances_.begin(); + iter != pending_instances_.end(); ++iter) { if (iter->second->instance()->Matches(instance)) return iter->second; }
diff --git a/content/browser/shared_worker/shared_worker_service_impl.h b/content/browser/shared_worker/shared_worker_service_impl.h index 99296d6..ea68ae6 100644 --- a/content/browser/shared_worker/shared_worker_service_impl.h +++ b/content/browser/shared_worker/shared_worker_service_impl.h
@@ -110,7 +110,7 @@ typedef base::ScopedPtrHashMap<ProcessRouteIdPair, scoped_ptr<SharedWorkerHost>> WorkerHostMap; typedef base::ScopedPtrHashMap<int, scoped_ptr<SharedWorkerPendingInstance>> - PendingInstaneMap; + PendingInstanceMap; SharedWorkerServiceImpl(); ~SharedWorkerServiceImpl() override; @@ -163,7 +163,7 @@ static bool (*s_try_increment_worker_ref_count_)(int); WorkerHostMap worker_hosts_; - PendingInstaneMap pending_instances_; + PendingInstanceMap pending_instances_; int next_pending_instance_id_; base::ObserverList<WorkerServiceObserver> observers_;
diff --git a/content/browser/ssl/ssl_cert_error_handler.cc b/content/browser/ssl/ssl_cert_error_handler.cc index 9ec7885..54b165d9 100644 --- a/content/browser/ssl/ssl_cert_error_handler.cc +++ b/content/browser/ssl/ssl_cert_error_handler.cc
@@ -15,19 +15,12 @@ const base::WeakPtr<Delegate>& delegate, ResourceType resource_type, const GURL& url, - int render_process_id, - int render_frame_id, const net::SSLInfo& ssl_info, bool fatal) - : SSLErrorHandler(delegate, - resource_type, - url, - render_process_id, - render_frame_id), + : SSLErrorHandler(delegate, resource_type, url), ssl_info_(ssl_info), cert_error_(net::MapCertStatusToNetError(ssl_info.cert_status)), - fatal_(fatal) { -} + fatal_(fatal) {} SSLCertErrorHandler* SSLCertErrorHandler::AsSSLCertErrorHandler() { return this;
diff --git a/content/browser/ssl/ssl_cert_error_handler.h b/content/browser/ssl/ssl_cert_error_handler.h index e3c4378..11174ed0 100644 --- a/content/browser/ssl/ssl_cert_error_handler.h +++ b/content/browser/ssl/ssl_cert_error_handler.h
@@ -22,8 +22,6 @@ SSLCertErrorHandler(const base::WeakPtr<Delegate>& delegate, ResourceType resource_type, const GURL& url, - int render_process_id, - int render_frame_id, const net::SSLInfo& ssl_info, bool fatal);
diff --git a/content/browser/ssl/ssl_error_handler.cc b/content/browser/ssl/ssl_error_handler.cc index 45b6dfd..40b2b564 100644 --- a/content/browser/ssl/ssl_error_handler.cc +++ b/content/browser/ssl/ssl_error_handler.cc
@@ -20,13 +20,9 @@ SSLErrorHandler::SSLErrorHandler(const base::WeakPtr<Delegate>& delegate, ResourceType resource_type, - const GURL& url, - int render_process_id, - int render_frame_id) + const GURL& url) : manager_(NULL), delegate_(delegate), - render_process_id_(render_process_id), - render_frame_id_(render_frame_id), request_url_(url), resource_type_(resource_type), request_has_been_notified_(false) { @@ -55,13 +51,11 @@ return NULL; } -void SSLErrorHandler::Dispatch() { +void SSLErrorHandler::Dispatch( + const base::Callback<WebContents*(void)>& web_contents_getter) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - WebContents* web_contents = NULL; - RenderFrameHost* render_frame_host = - RenderFrameHost::FromID(render_process_id_, render_frame_id_); - web_contents = WebContents::FromRenderFrameHost(render_frame_host); + WebContents* web_contents = web_contents_getter.Run(); if (!web_contents) { // We arrived on the UI thread, but the tab we're looking for is no longer @@ -116,6 +110,11 @@ base::Bind(&SSLErrorHandler::CompleteTakeNoAction, this)); } +SSLManager* SSLErrorHandler::GetManager() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return manager_; +} + void SSLErrorHandler::CompleteCancelRequest(int error) { DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/content/browser/ssl/ssl_error_handler.h b/content/browser/ssl/ssl_error_handler.h index 26fc147..3596d47 100644 --- a/content/browser/ssl/ssl_error_handler.h +++ b/content/browser/ssl/ssl_error_handler.h
@@ -25,6 +25,7 @@ class ResourceDispatcherHostImpl; class SSLCertErrorHandler; class SSLManager; +class WebContents; // An SSLErrorHandler carries information from the IO thread to the UI thread // and is dispatched to the appropriate SSLManager when it arrives on the @@ -65,7 +66,7 @@ // this error. // // Call on UI thread. - void Dispatch(); + void Dispatch(const base::Callback<WebContents*(void)>& web_contents_getter); // Available on either thread. const GURL& request_url() const { return request_url_; } @@ -96,8 +97,9 @@ // call this. void TakeNoAction(); - int render_process_id() const { return render_process_id_; } - int render_frame_id() const { return render_frame_id_; } + // Returns the manager associated with this SSLErrorHandler. + // Should only be accessed on the UI thread. + SSLManager* GetManager() const; protected: friend class base::RefCountedThreadSafe<SSLErrorHandler>; @@ -105,9 +107,7 @@ // Construct on the IO thread. SSLErrorHandler(const base::WeakPtr<Delegate>& delegate, ResourceType resource_type, - const GURL& url, - int render_process_id, - int render_frame_id); + const GURL& url); virtual ~SSLErrorHandler(); @@ -137,11 +137,6 @@ // Call on the IO thread. void CompleteTakeNoAction(); - // We use these members to find the correct SSLManager when we arrive on - // the UI thread. - int render_process_id_; - int render_frame_id_; - // The URL that we requested. // This read-only member can be accessed on any thread. const GURL request_url_;
diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc index e4c71e3..cd6c2bea 100644 --- a/content/browser/ssl/ssl_manager.cc +++ b/content/browser/ssl/ssl_manager.cc
@@ -51,8 +51,7 @@ const base::WeakPtr<SSLErrorHandler::Delegate>& delegate, const ResourceType resource_type, const GURL& url, - int render_process_id, - int render_frame_id, + const base::Callback<WebContents*(void)>& web_contents_getter, const net::SSLInfo& ssl_info, bool fatal) { DCHECK(delegate.get()); @@ -60,8 +59,6 @@ << net::MapCertStatusToNetError(ssl_info.cert_status) << " resource_type: " << resource_type << " url: " << url.spec() - << " render_process_id: " << render_process_id - << " render_frame_id: " << render_frame_id << " cert_status: " << std::hex << ssl_info.cert_status; // A certificate error occurred. Construct a SSLCertErrorHandler object and @@ -69,13 +66,23 @@ BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&SSLCertErrorHandler::Dispatch, - new SSLCertErrorHandler(delegate, - resource_type, - url, - render_process_id, - render_frame_id, - ssl_info, - fatal))); + new SSLCertErrorHandler(delegate, resource_type, url, ssl_info, + fatal), + web_contents_getter)); +} + +// static +void SSLManager::OnSSLCertificateSubresourceError( + const base::WeakPtr<SSLErrorHandler::Delegate>& delegate, + const GURL& url, + int render_process_id, + int render_frame_id, + const net::SSLInfo& ssl_info, + bool fatal) { + OnSSLCertificateError(delegate, RESOURCE_TYPE_SUB_RESOURCE, url, + base::Bind(&WebContentsImpl::FromRenderFrameHostID, + render_process_id, render_frame_id), + ssl_info, fatal); } // static
diff --git a/content/browser/ssl/ssl_manager.h b/content/browser/ssl/ssl_manager.h index 8128ee8..6e46705 100644 --- a/content/browser/ssl/ssl_manager.h +++ b/content/browser/ssl/ssl_manager.h
@@ -52,6 +52,16 @@ const base::WeakPtr<SSLErrorHandler::Delegate>& delegate, ResourceType resource_type, const GURL& url, + const base::Callback<WebContents*(void)>& web_contents_getter, + const net::SSLInfo& ssl_info, + bool fatal); + + // Same as the above, and only works for subresources. Prefer using + // OnSSLCertificateError whenever possible (ie when you have access to the + // WebContents). + static void OnSSLCertificateSubresourceError( + const base::WeakPtr<SSLErrorHandler::Delegate>& delegate, + const GURL& url, int render_process_id, int render_frame_id, const net::SSLInfo& ssl_info,
diff --git a/content/browser/ssl/ssl_policy.cc b/content/browser/ssl/ssl_policy.cc index dab2a5a..ed8d80b3 100644 --- a/content/browser/ssl/ssl_policy.cc +++ b/content/browser/ssl/ssl_policy.cc
@@ -232,17 +232,11 @@ CertificateRequestResultType result = CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE; GetContentClient()->browser()->AllowCertificateError( - handler->render_process_id(), - handler->render_frame_id(), - handler->cert_error(), - handler->ssl_info(), - handler->request_url(), - handler->resource_type(), - overridable, - strict_enforcement, + handler->GetManager()->controller()->GetWebContents(), + handler->cert_error(), handler->ssl_info(), handler->request_url(), + handler->resource_type(), overridable, strict_enforcement, expired_previous_decision, - base::Bind(&SSLPolicy::OnAllowCertificate, - base::Unretained(this), + base::Bind(&SSLPolicy::OnAllowCertificate, base::Unretained(this), make_scoped_refptr(handler)), &result); switch (result) {
diff --git a/content/browser/streams/stream_url_request_job.cc b/content/browser/streams/stream_url_request_job.cc index 0392d108f..e26fe35 100644 --- a/content/browser/streams/stream_url_request_job.cc +++ b/content/browser/streams/stream_url_request_job.cc
@@ -40,8 +40,6 @@ } void StreamURLRequestJob::OnDataAvailable(Stream* stream) { - // Clear the IO_PENDING status. - SetStatus(net::URLRequestStatus()); // Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData() // operation waiting for IO completion. if (!pending_buffer_.get()) @@ -50,24 +48,22 @@ // pending_buffer_ is set to the IOBuffer instance provided to ReadRawData() // by URLRequestJob. - int bytes_read; + int result = 0; switch (stream_->ReadRawData(pending_buffer_.get(), pending_buffer_size_, - &bytes_read)) { + &result)) { case Stream::STREAM_HAS_DATA: - DCHECK_GT(bytes_read, 0); + DCHECK_GT(result, 0); break; case Stream::STREAM_COMPLETE: - // Ensure this. Calling NotifyReadComplete call with 0 signals - // completion. - bytes_read = 0; + // Ensure ReadRawData gives net::OK. + DCHECK_EQ(net::OK, result); break; case Stream::STREAM_EMPTY: NOTREACHED(); break; case Stream::STREAM_ABORTED: // Handle this as connection reset. - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_CONNECTION_RESET)); + result = net::ERR_CONNECTION_RESET; break; } @@ -76,8 +72,9 @@ pending_buffer_ = NULL; pending_buffer_size_ = 0; - total_bytes_read_ += bytes_read; - NotifyReadComplete(bytes_read); + if (result > 0) + total_bytes_read_ += result; + ReadRawDataComplete(result); } // net::URLRequestJob methods. @@ -94,43 +91,40 @@ ClearStream(); } -bool StreamURLRequestJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int StreamURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { + // TODO(ellyjones): This is not right. The old code returned true here, but + // ReadRawData's old contract was to return true only for synchronous + // successes, which had the effect of treating all errors as synchronous EOFs. + // See https://crbug.com/508957 if (request_failed_) - return true; + return 0; DCHECK(buf); - DCHECK(bytes_read); int to_read = buf_size; if (max_range_ && to_read) { if (to_read + total_bytes_read_ > max_range_) to_read = max_range_ - total_bytes_read_; - if (to_read <= 0) { - *bytes_read = 0; - return true; - } + if (to_read == 0) + return 0; } - switch (stream_->ReadRawData(buf, to_read, bytes_read)) { + int bytes_read = 0; + switch (stream_->ReadRawData(buf, to_read, &bytes_read)) { case Stream::STREAM_HAS_DATA: case Stream::STREAM_COMPLETE: - total_bytes_read_ += *bytes_read; - return true; + total_bytes_read_ += bytes_read; + return bytes_read; case Stream::STREAM_EMPTY: pending_buffer_ = buf; pending_buffer_size_ = to_read; - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; + return net::ERR_IO_PENDING; case Stream::STREAM_ABORTED: // Handle this as connection reset. - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_CONNECTION_RESET)); - return false; + return net::ERR_CONNECTION_RESET; } NOTREACHED(); - return false; + return net::ERR_FAILED; } bool StreamURLRequestJob::GetMimeType(std::string* mime_type) const { @@ -189,13 +183,8 @@ void StreamURLRequestJob::NotifyFailure(int error_code) { request_failed_ = true; - // If we already return the headers on success, we can't change the headers - // now. Instead, we just error out. - if (headers_set_) { - NotifyDone( - net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code)); - return; - } + // This method can only be called before headers are set. + DCHECK(!headers_set_); // TODO(zork): Share these with BlobURLRequestJob. net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR;
diff --git a/content/browser/streams/stream_url_request_job.h b/content/browser/streams/stream_url_request_job.h index 05c9551..f22311d 100644 --- a/content/browser/streams/stream_url_request_job.h +++ b/content/browser/streams/stream_url_request_job.h
@@ -29,7 +29,7 @@ // net::URLRequestJob methods. void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override;
diff --git a/content/browser/tcmalloc_internals_request_job.cc b/content/browser/tcmalloc_internals_request_job.cc deleted file mode 100644 index e55df5e..0000000 --- a/content/browser/tcmalloc_internals_request_job.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/tcmalloc_internals_request_job.h" - -#include "base/allocator/allocator_extension.h" -#include "content/common/child_process_messages.h" -#include "content/public/browser/browser_child_process_host_iterator.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/common/process_type.h" -#include "net/base/net_errors.h" - -namespace content { - -// static -AboutTcmallocOutputs* AboutTcmallocOutputs::GetInstance() { - return base::Singleton<AboutTcmallocOutputs>::get(); -} - -AboutTcmallocOutputs::AboutTcmallocOutputs() {} - -AboutTcmallocOutputs::~AboutTcmallocOutputs() {} - -void AboutTcmallocOutputs::OnStatsForChildProcess( - base::ProcessId pid, int process_type, - const std::string& output) { - std::string header = GetProcessTypeNameInEnglish(process_type); - base::StringAppendF(&header, " PID %d", static_cast<int>(pid)); - SetOutput(header, output); -} - -void AboutTcmallocOutputs::SetOutput(const std::string& header, - const std::string& output) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - outputs_[header] = output; -} - -void AboutTcmallocOutputs::DumpToHTMLTable(std::string* data) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - data->append("<table width=\"100%\">\n"); - for (AboutTcmallocOutputsType::const_iterator oit = outputs_.begin(); - oit != outputs_.end(); - oit++) { - data->append("<tr><td bgcolor=\"yellow\">"); - data->append(oit->first); - data->append("</td></tr>\n"); - data->append("<tr><td><pre>\n"); - data->append(oit->second); - data->append("</pre></td></tr>\n"); - } - data->append("</table>\n"); - outputs_.clear(); -} - -TcmallocInternalsRequestJob::TcmallocInternalsRequestJob( - net::URLRequest* request, net::NetworkDelegate* network_delegate) - : net::URLRequestSimpleJob(request, network_delegate) { -} - -#if defined(USE_TCMALLOC) -void RequestTcmallocStatsFromChildRenderProcesses() { - RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); - while (!it.IsAtEnd()) { - it.GetCurrentValue()->Send(new ChildProcessMsg_GetTcmallocStats); - it.Advance(); - } -} - -void AboutTcmalloc(std::string* data) { - data->append("<!DOCTYPE html>\n<html>\n<head>\n"); - data->append( - "<meta http-equiv=\"Content-Security-Policy\" " - "content=\"object-src 'none'; script-src 'none'\">"); - data->append("<title>tcmalloc stats</title>"); - data->append("</head><body>"); - - // Display any stats for which we sent off requests the last time. - data->append("<p>Stats as of last page load;"); - data->append("reload to get stats as of this page load.</p>\n"); - data->append("<table width=\"100%\">\n"); - - AboutTcmallocOutputs::GetInstance()->DumpToHTMLTable(data); - - data->append("</body></html>\n"); - - // Populate the collector with stats from the local browser process - // and send off requests to all the renderer processes. - char buffer[1024 * 32]; - base::allocator::GetStats(buffer, sizeof(buffer)); - std::string browser("Browser"); - AboutTcmallocOutputs::GetInstance()->SetOutput(browser, buffer); - - for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { - iter.Send(new ChildProcessMsg_GetTcmallocStats); - } - - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( - &RequestTcmallocStatsFromChildRenderProcesses)); -} -#endif - -int TcmallocInternalsRequestJob::GetData( - std::string* mime_type, - std::string* charset, - std::string* data, - const net::CompletionCallback& callback) const { - mime_type->assign("text/html"); - charset->assign("UTF8"); - - data->clear(); -#if defined(USE_TCMALLOC) - AboutTcmalloc(data); -#endif - return net::OK; -} - -} // namespace content
diff --git a/content/browser/tcmalloc_internals_request_job.h b/content/browser/tcmalloc_internals_request_job.h deleted file mode 100644 index 2d57a10d..0000000 --- a/content/browser/tcmalloc_internals_request_job.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_TCMALLOC_INTERNALS_REQUEST_JOB_H_ -#define CONTENT_BROWSER_TCMALLOC_INTERNALS_REQUEST_JOB_H_ - -#include <map> -#include "base/basictypes.h" -#include "base/memory/singleton.h" -#include "base/process/process.h" -#include "build/build_config.h" // USE_TCMALLOC -#include "net/url_request/url_request_simple_job.h" - -namespace content { - -class AboutTcmallocOutputs { - public: - // Returns the singleton instance. - static AboutTcmallocOutputs* GetInstance(); - - // Records the output for a specified header string. - void SetOutput(const std::string& header, const std::string& output); - - void DumpToHTMLTable(std::string* data); - - // Callback for output returned from a child process. Adds - // the output for a canonical process-specific header string that - // incorporates the pid. - void OnStatsForChildProcess(base::ProcessId pid, - int process_type, - const std::string& output); - - private: - AboutTcmallocOutputs(); - ~AboutTcmallocOutputs(); - - // A map of header strings (e.g. "Browser", "Renderer PID 123") - // to the tcmalloc output collected for each process. - typedef std::map<std::string, std::string> AboutTcmallocOutputsType; - AboutTcmallocOutputsType outputs_; - - friend struct base::DefaultSingletonTraits<AboutTcmallocOutputs>; - - DISALLOW_COPY_AND_ASSIGN(AboutTcmallocOutputs); -}; - -class TcmallocInternalsRequestJob : public net::URLRequestSimpleJob { - public: - TcmallocInternalsRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate); - - int GetData(std::string* mime_type, - std::string* charset, - std::string* data, - const net::CompletionCallback& callback) const override; - - protected: - ~TcmallocInternalsRequestJob() override {} - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(TcmallocInternalsRequestJob); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_TCMALLOC_INTERNALS_REQUEST_JOB_H_
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 273f864..c36e3a7 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -566,6 +566,18 @@ WebContents::FromRenderFrameHost(frame_tree_node->current_frame_host())); } +// static +WebContents* WebContentsImpl::FromRenderFrameHostID(int render_process_host_id, + int render_frame_host_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + RenderFrameHost* render_frame_host = + RenderFrameHost::FromID(render_process_host_id, render_frame_host_id); + if (!render_frame_host) + return nullptr; + + return WebContents::FromRenderFrameHost(render_frame_host); +} + RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() { return GetRenderManager(); } @@ -1497,17 +1509,20 @@ delegate_->LostCapture(); } +void WebContentsImpl::RenderWidgetCreated( + RenderWidgetHostImpl* render_widget_host) { + created_widgets_.insert(render_widget_host); +} + void WebContentsImpl::RenderWidgetDeleted( RenderWidgetHostImpl* render_widget_host) { - if (is_being_destroyed_) { - // |created_widgets_| might have been destroyed. - return; - } + // Note that |is_being_destroyed_| can be true at this point as + // ~WebContentsImpl() calls RFHM::ClearRFHsPendingShutdown(), which might lead + // us here. + created_widgets_.erase(render_widget_host); - std::set<RenderWidgetHostImpl*>::iterator iter = - created_widgets_.find(render_widget_host); - if (iter != created_widgets_.end()) - created_widgets_.erase(iter); + if (is_being_destroyed_) + return; if (render_widget_host && render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) { @@ -1923,7 +1938,6 @@ RenderWidgetHostImpl* widget_host = new RenderWidgetHostImpl(this, process, route_id, IsHidden()); - created_widgets_.insert(widget_host); RenderWidgetHostViewBase* widget_view = static_cast<RenderWidgetHostViewBase*>(
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 441cedc2..8d55780 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -113,6 +113,8 @@ static std::vector<WebContentsImpl*> GetAllWebContents(); static WebContentsImpl* FromFrameTreeNode(FrameTreeNode* frame_tree_node); + static WebContents* FromRenderFrameHostID(int render_process_host_id, + int render_frame_host_id); // Creates a swapped out RenderView. This is used by the browser plugin to // create a swapped out RenderView in the embedder render process for the @@ -560,6 +562,7 @@ // RenderWidgetHostDelegate -------------------------------------------------- + void RenderWidgetCreated(RenderWidgetHostImpl* render_widget_host) override; void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override; void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) override; void RenderWidgetWasResized(RenderWidgetHostImpl* render_widget_host,
diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc index 44302df1..e539166 100644 --- a/content/browser/webui/url_data_manager_backend.cc +++ b/content/browser/webui/url_data_manager_backend.cc
@@ -26,7 +26,6 @@ #include "content/browser/net/view_blob_internals_job_factory.h" #include "content/browser/net/view_http_cache_job_factory.h" #include "content/browser/resource_context_impl.h" -#include "content/browser/tcmalloc_internals_request_job.h" #include "content/browser/webui/shared_resources_data_source.h" #include "content/browser/webui/url_data_source_impl.h" #include "content/public/browser/browser_context.h" @@ -119,7 +118,7 @@ // net::URLRequestJob implementation. void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; bool GetMimeType(std::string* mime_type) const override; int GetResponseCode() const override; void GetResponseInfo(net::HttpResponseInfo* info) override; @@ -190,8 +189,9 @@ bool RequiresUnsafeEval() const; // Do the actual copy from data_ (the data we're serving) into |buf|. - // Separate from ReadRawData so we can handle async I/O. - void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read); + // Separate from ReadRawData so we can handle async I/O. Returns the number of + // bytes read. + int CompleteRead(net::IOBuffer* buf, int buf_size); // The actual data we're serving. NULL until it's been fetched. scoped_refptr<base::RefCountedMemory> data_; @@ -336,22 +336,16 @@ void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); if (bytes) { - // The request completed, and we have all the data. - // Clear any IO pending status. - SetStatus(net::URLRequestStatus()); - data_ = bytes; - int bytes_read; if (pending_buf_.get()) { CHECK(pending_buf_->data()); - CompleteRead(pending_buf_.get(), pending_buf_size_, &bytes_read); + int result = CompleteRead(pending_buf_.get(), pending_buf_size_); pending_buf_ = NULL; - NotifyReadComplete(bytes_read); + ReadRawDataComplete(result); } } else { // The request failed. - NotifyDone( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); + ReadRawDataComplete(net::ERR_FAILED); } } @@ -359,27 +353,21 @@ return weak_factory_.GetWeakPtr(); } -bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { if (!data_.get()) { - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); DCHECK(!pending_buf_.get()); CHECK(buf->data()); pending_buf_ = buf; pending_buf_size_ = buf_size; - return false; // Tell the caller we're still waiting for data. + return net::ERR_IO_PENDING; } // Otherwise, the data is available. - CompleteRead(buf, buf_size, bytes_read); - return true; + return CompleteRead(buf, buf_size); } -void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { - int remaining = static_cast<int>(data_->size()) - data_offset_; +int URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size) { + int remaining = data_->size() - data_offset_; if (buf_size > remaining) buf_size = remaining; if (buf_size > 0) { @@ -391,7 +379,7 @@ memcpy(buf->data(), data_->front() + data_offset_, buf_size); data_offset_ += buf_size; } - *bytes_read = buf_size; + return buf_size; } void URLRequestChromeJob::CheckStoragePartitionMatches( @@ -495,14 +483,6 @@ request, network_delegate, blob_storage_context_->context()); } -#if defined(USE_TCMALLOC) - // Next check for chrome://tcmalloc/, which uses its own job type. - if (request->url().SchemeIs(kChromeUIScheme) && - request->url().host() == kChromeUITcmallocHost) { - return new TcmallocInternalsRequestJob(request, network_delegate); - } -#endif - // Next check for chrome://histograms/, which uses its own job type. if (request->url().SchemeIs(kChromeUIScheme) && request->url().host() == kChromeUIHistogramHost) {
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index b21a722..ccaa67e 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -8,7 +8,6 @@ #include <vector> -#include "base/allocator/allocator_extension.h" #include "base/bind.h" #include "base/files/file_path.h" #include "base/location.h" @@ -16,7 +15,6 @@ #include "base/memory/singleton.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" -#include "base/process/process_metrics.h" #include "base/rand_util.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" @@ -1251,18 +1249,6 @@ return static_cast<size_t>(base::SysInfo::NumberOfProcessors()); } -bool BlinkPlatformImpl::processMemorySizesInBytes( - size_t* private_bytes, - size_t* shared_bytes) { - scoped_ptr<base::ProcessMetrics> current_process_metrics( - base::ProcessMetrics::CreateCurrentProcessMetrics()); - return current_process_metrics->GetMemoryBytes(private_bytes, shared_bytes); -} - -bool BlinkPlatformImpl::memoryAllocatorWasteInBytes(size_t* size) { - return base::allocator::GetAllocatorWasteSize(size); -} - blink::WebDiscardableMemory* BlinkPlatformImpl::allocateAndLockDiscardableMemory(size_t bytes) { return content::WebDiscardableMemoryImpl::CreateLockedMemory(bytes).release();
diff --git a/content/child/blink_platform_impl.h b/content/child/blink_platform_impl.h index 6aab04ba..25c1649 100644 --- a/content/child/blink_platform_impl.h +++ b/content/child/blink_platform_impl.h
@@ -77,9 +77,6 @@ bool isLowEndDeviceMode() override; size_t numberOfProcessors() override; - bool processMemorySizesInBytes(size_t* private_bytes, - size_t* shared_bytes) override; - bool memoryAllocatorWasteInBytes(size_t* size) override; blink::WebDiscardableMemory* allocateAndLockDiscardableMemory( size_t bytes) override; size_t maxDecodedImageBytes() override;
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index be915a0..22007eb 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -8,7 +8,6 @@ #include <string> -#include "base/allocator/allocator_extension.h" #include "base/base_switches.h" #include "base/basictypes.h" #include "base/command_line.h" @@ -61,6 +60,7 @@ #include "ipc/ipc_sync_channel.h" #include "ipc/ipc_sync_message_filter.h" #include "ipc/mojo/ipc_channel_mojo.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" @@ -658,8 +658,9 @@ OnProcessBackgrounded) IPC_MESSAGE_HANDLER(MojoMsg_BindExternalMojoShellHandle, OnBindExternalMojoShellHandle) -#if defined(USE_TCMALLOC) - IPC_MESSAGE_HANDLER(ChildProcessMsg_GetTcmallocStats, OnGetTcmallocStats) +#if defined(OS_WIN) + IPC_MESSAGE_HANDLER(ChildProcessMsg_SetMojoParentPipeHandle, + OnSetMojoParentPipeHandle) #endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -730,13 +731,10 @@ #endif // defined(MOJO_SHELL_CLIENT) } -#if defined(USE_TCMALLOC) -void ChildThreadImpl::OnGetTcmallocStats() { - std::string result; - char buffer[1024 * 32]; - base::allocator::GetStats(buffer, sizeof(buffer)); - result.append(buffer); - Send(new ChildProcessHostMsg_TcmallocStats(result)); +#if defined(OS_WIN) +void ChildThreadImpl::OnSetMojoParentPipeHandle( + const IPC::PlatformFileForTransit& file) { + mojo::embedder::SetParentPipeHandle(file); } #endif
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h index eb90f70..4e4270d 100644 --- a/content/child/child_thread_impl.h +++ b/content/child/child_thread_impl.h
@@ -235,8 +235,8 @@ #ifdef IPC_MESSAGE_LOG_ENABLED void OnSetIPCLoggingEnabled(bool enable); #endif -#if defined(USE_TCMALLOC) - void OnGetTcmallocStats(); +#if defined(OS_WIN) + void OnSetMojoParentPipeHandle(const IPC::PlatformFileForTransit& file); #endif void EnsureConnected();
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h index da73059..c7f4208 100644 --- a/content/common/child_process_messages.h +++ b/content/common/child_process_messages.h
@@ -15,7 +15,8 @@ #include "content/common/content_export.h" #include "content/common/host_discardable_shared_memory_manager.h" #include "gpu/command_buffer/common/sync_token.h" -#include "ipc/ipc_message_macros.h" +#include "ipc/ipc_message_macros.h" +#include "ipc/ipc_platform_file.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/ipc/gfx_param_traits.h" @@ -120,11 +121,6 @@ IPC_MESSAGE_CONTROL1(ChildProcessMsg_SetProcessBackgrounded, bool /* background */) -#if defined(USE_TCMALLOC) -// Sent to child process to request tcmalloc stats. -IPC_MESSAGE_CONTROL0(ChildProcessMsg_GetTcmallocStats) -#endif - #if defined(OS_MACOSX) // Sent to child processes to tell them what token to use when registering // and/or acquiring IOSurfaces. @@ -132,6 +128,12 @@ content::IOSurfaceManagerToken /* token */) #endif +#if defined(OS_WIN) +// Sends a pipe used by the child process to broker passing of Mojo handles. +IPC_MESSAGE_CONTROL1(ChildProcessMsg_SetMojoParentPipeHandle, + IPC::PlatformFileForTransit /* handle */) +#endif + #if defined(USE_OZONE) // Sent to child processes to initialize ClientNativePixmapFactory using // a device file descriptor. @@ -194,12 +196,6 @@ IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_DeletedSharedBitmap, cc::SharedBitmapId) -#if defined(USE_TCMALLOC) -// Reply to ChildProcessMsg_GetTcmallocStats. -IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TcmallocStats, - std::string /* output */) -#endif - // Asks the browser to create a gpu memory buffer. IPC_SYNC_MESSAGE_CONTROL5_1(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer, gfx::GpuMemoryBufferId /* new_id */,
diff --git a/content/common/host_shared_bitmap_manager.cc b/content/common/host_shared_bitmap_manager.cc index f913dba..6a9595e 100644 --- a/content/common/host_shared_bitmap_manager.cc +++ b/content/common/host_shared_bitmap_manager.cc
@@ -74,7 +74,10 @@ base::SharedMemoryHandle* shared_memory_handle) { manager_->AllocateSharedBitmapForChild(process_handle, buffer_size, id, shared_memory_handle); - owned_bitmaps_.insert(id); + if (*shared_memory_handle != base::SharedMemory::NULLHandle()) { + base::AutoLock lock(lock_); + owned_bitmaps_.insert(id); + } } void HostSharedBitmapManagerClient::ChildAllocatedSharedBitmap( @@ -82,14 +85,20 @@ const base::SharedMemoryHandle& handle, base::ProcessHandle process_handle, const cc::SharedBitmapId& id) { - manager_->ChildAllocatedSharedBitmap(buffer_size, handle, process_handle, id); - owned_bitmaps_.insert(id); + if (manager_->ChildAllocatedSharedBitmap(buffer_size, handle, process_handle, + id)) { + base::AutoLock lock(lock_); + owned_bitmaps_.insert(id); + } } void HostSharedBitmapManagerClient::ChildDeletedSharedBitmap( const cc::SharedBitmapId& id) { manager_->ChildDeletedSharedBitmap(id); - owned_bitmaps_.erase(id); + { + base::AutoLock lock(lock_); + owned_bitmaps_.erase(id); + } } HostSharedBitmapManager::HostSharedBitmapManager() {} @@ -176,14 +185,14 @@ return true; } -void HostSharedBitmapManager::ChildAllocatedSharedBitmap( +bool HostSharedBitmapManager::ChildAllocatedSharedBitmap( size_t buffer_size, const base::SharedMemoryHandle& handle, base::ProcessHandle process_handle, const cc::SharedBitmapId& id) { base::AutoLock lock(lock_); if (handle_map_.find(id) != handle_map_.end()) - return; + return false; scoped_refptr<BitmapData> data( new BitmapData(process_handle, buffer_size)); @@ -195,8 +204,9 @@ data->memory = make_scoped_ptr(new base::SharedMemory(handle, false)); #endif - data->memory->Map(data->buffer_size); - data->memory->Close(); + data->memory->Map(data->buffer_size); + data->memory->Close(); + return true; } void HostSharedBitmapManager::AllocateSharedBitmapForChild(
diff --git a/content/common/host_shared_bitmap_manager.h b/content/common/host_shared_bitmap_manager.h index b14bb0b3..5ff8212a 100644 --- a/content/common/host_shared_bitmap_manager.h +++ b/content/common/host_shared_bitmap_manager.h
@@ -51,6 +51,9 @@ private: HostSharedBitmapManager* manager_; + + // Lock must be held around access to owned_bitmaps_. + base::Lock lock_; base::hash_set<cc::SharedBitmapId> owned_bitmaps_; DISALLOW_COPY_AND_ASSIGN(HostSharedBitmapManagerClient); @@ -88,7 +91,7 @@ size_t buffer_size, const cc::SharedBitmapId& id, base::SharedMemoryHandle* shared_memory_handle); - void ChildAllocatedSharedBitmap(size_t buffer_size, + bool ChildAllocatedSharedBitmap(size_t buffer_size, const base::SharedMemoryHandle& handle, base::ProcessHandle process_handle, const cc::SharedBitmapId& id);
diff --git a/content/common/render_process_messages.h b/content/common/render_process_messages.h index 8135b2c..2778a3b 100644 --- a/content/common/render_process_messages.h +++ b/content/common/render_process_messages.h
@@ -55,11 +55,6 @@ IPC_MESSAGE_CONTROL1(RenderProcessHostMsg_SuddenTerminationChanged, bool /* enabled */) -// Asks the browser for the renderer process memory size stats. -IPC_SYNC_MESSAGE_CONTROL0_2(RenderProcessHostMsg_GetProcessMemorySizes, - size_t /* private_bytes */, - size_t /* shared_bytes */) - #if defined(OS_MACOSX) // Request that the browser load a font into shared memory for us. IPC_SYNC_MESSAGE_CONTROL1_3(RenderProcessHostMsg_LoadFont,
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index d9704651..276af0c 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -33,7 +33,6 @@ '../ui/accessibility/accessibility.gyp:ax_gen', '../ui/base/ui_base.gyp:ui_base', '../ui/base/ime/ui_base_ime.gyp:ui_base_ime', - '../ui/events/events.gyp:blink', '../ui/events/events.gyp:events', '../ui/events/events.gyp:events_base', '../ui/events/events.gyp:gesture_detection', @@ -1459,8 +1458,6 @@ 'browser/streams/stream_write_observer.h', 'browser/system_message_window_win.cc', 'browser/system_message_window_win.h', - 'browser/tcmalloc_internals_request_job.cc', - 'browser/tcmalloc_internals_request_job.h', 'browser/theme_helper_mac.h', 'browser/theme_helper_mac.mm', 'browser/time_zone_monitor.cc', @@ -1854,6 +1851,7 @@ '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings', '../third_party/mojo/mojo_public.gyp:mojo_js_bindings', + '../ui/events/blink/events_blink.gyp:events_blink', '../ui/surface/surface.gyp:surface', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection', ],
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 360a17c..5c566e7 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi
@@ -39,6 +39,7 @@ '../third_party/npapi/npapi.gyp:npapi', '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h', '../ui/accessibility/accessibility.gyp:accessibility', + '../ui/events/blink/events_blink.gyp:events_blink', '../ui/events/events.gyp:dom_keycode_converter', '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', @@ -147,8 +148,6 @@ 'renderer/context_menu_params_builder.h', 'renderer/cursor_utils.cc', 'renderer/cursor_utils.h', - 'renderer/date_time_suggestion_builder.cc', - 'renderer/date_time_suggestion_builder.h', 'renderer/device_sensors/device_light_event_pump.cc', 'renderer/device_sensors/device_light_event_pump.h', 'renderer/device_sensors/device_motion_event_pump.cc', @@ -234,15 +233,10 @@ 'renderer/input/input_handler_manager.cc', 'renderer/input/input_handler_manager.h', 'renderer/input/input_handler_manager_client.h', - 'renderer/input/input_handler_proxy.cc', - 'renderer/input/input_handler_proxy.h', 'renderer/input/input_handler_wrapper.cc', 'renderer/input/input_handler_wrapper.h', - 'renderer/input/input_scroll_elasticity_controller.cc', - 'renderer/input/input_scroll_elasticity_controller.h', 'renderer/input/main_thread_input_event_filter.cc', 'renderer/input/main_thread_input_event_filter.h', - 'renderer/input/synchronous_input_handler_proxy.h', 'renderer/internal_document_state_data.cc', 'renderer/internal_document_state_data.h', 'renderer/java/gin_java_bridge_dispatcher.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index ba521a2..f3859ee 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -690,8 +690,6 @@ 'renderer/gpu/render_widget_compositor_unittest.cc', 'renderer/ico_image_decoder_unittest.cc', 'renderer/input/input_event_filter_unittest.cc', - 'renderer/input/input_handler_proxy_unittest.cc', - 'renderer/input/input_scroll_elasticity_controller_unittest.cc', 'renderer/peripheral_content_heuristic_unittest.cc', 'renderer/manifest/manifest_parser_unittest.cc', 'renderer/media/android/media_info_loader_unittest.cc', @@ -1145,7 +1143,7 @@ '../third_party/WebKit/public/blink.gyp:blink', '../ui/accessibility/accessibility.gyp:accessibility', '../ui/base/ui_base.gyp:ui_base', - '../ui/events/events.gyp:blink', + '../ui/events/blink/events_blink.gyp:events_blink', '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc', @@ -1658,6 +1656,8 @@ ['chromeos==1 or OS=="win" or OS=="android"', { 'targets': [ { + # TODO(GYP): Port Windows and ChromeOS logic. + # GN: //content/test:video_decode_accelerator_unittest 'target_name': 'video_decode_accelerator_unittest', 'type': '<(gtest_target_type)', 'dependencies': [ @@ -2057,7 +2057,7 @@ 'includes': [ '../build/jni_generator.gypi' ], }, { - # TODO(GN) + # GN: //content/test:video_decode_accelerator_unittest_apk 'target_name': 'video_decode_accelerator_unittest_apk', 'type': 'none', 'dependencies': [
diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h index daa30f4..e72c72f9 100644 --- a/content/gpu/gpu_child_thread.h +++ b/content/gpu/gpu_child_thread.h
@@ -83,10 +83,6 @@ void OnDisableWatchdog(); void OnGpuSwitched(); -#if defined(USE_TCMALLOC) - void OnGetGpuTcmalloc(); -#endif - void BindProcessControlRequest( mojo::InterfaceRequest<ProcessControl> request);
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java index 98538e4..5201472c 100644 --- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java +++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
@@ -17,6 +17,7 @@ import org.chromium.base.BaseSwitches; import org.chromium.base.CommandLine; +import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -211,7 +212,7 @@ mMainThread.wait(); } } - ContentMain.initApplicationContext(sContext.get().getApplicationContext()); + ContextUtils.initApplicationContext(sContext.get().getApplicationContext()); for (FileDescriptorInfo fdInfo : mFdInfos) { nativeRegisterGlobalFileDescriptor( fdInfo.mId, fdInfo.mFd.detachFd(), fdInfo.mOffset, fdInfo.mSize);
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentMain.java b/content/public/android/java/src/org/chromium/content/app/ContentMain.java index 7c542d5..ac992f4 100644 --- a/content/public/android/java/src/org/chromium/content/app/ContentMain.java +++ b/content/public/android/java/src/org/chromium/content/app/ContentMain.java
@@ -4,8 +4,6 @@ package org.chromium.content.app; -import android.content.Context; - import org.chromium.base.annotations.JNINamespace; /** @@ -21,19 +19,11 @@ @JNINamespace("content") public class ContentMain { /** - * Initialize application context in native side. - **/ - public static void initApplicationContext(Context context) { - nativeInitApplicationContext(context); - } - - /** * Start the ContentMainRunner in native side. **/ public static int start() { return nativeStart(); } - private static native void nativeInitApplicationContext(Context context); private static native int nativeStart(); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java index 4bc3154..6c97f4c 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java +++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java
@@ -7,6 +7,7 @@ import android.content.Context; import android.os.Handler; +import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.ResourceExtractor; import org.chromium.base.ThreadUtils; @@ -291,7 +292,7 @@ // TODO(yfriedman): Remove dependency on a command line flag for this. DeviceUtils.addDeviceSpecificUserAgentSwitch(mContext); - ContentMain.initApplicationContext(mContext); + ContextUtils.initApplicationContext(mContext); nativeSetCommandLineFlags( singleProcess, nativeIsPluginEnabled() ? getPlugins() : null); mPostResourceExtractionTasksCompleted = true; @@ -319,7 +320,7 @@ resourceExtractor.startExtractingResources(); resourceExtractor.waitForCompletion(); - ContentMain.initApplicationContext(mContext.getApplicationContext()); + ContextUtils.initApplicationContext(mContext.getApplicationContext()); nativeSetCommandLineFlags(false, null); }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 2145e44..d3d9f01 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -464,8 +464,7 @@ // asynchronously. If |result| is not set to // CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE, the request will be cancelled // or denied immediately, and the callback won't be run. - virtual void AllowCertificateError(int render_process_id, - int render_frame_id, + virtual void AllowCertificateError(WebContents* web_contents, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url,
diff --git a/content/public/browser/resource_request_info.h b/content/public/browser/resource_request_info.h index b6edad7..50b04bf 100644 --- a/content/public/browser/resource_request_info.h +++ b/content/public/browser/resource_request_info.h
@@ -65,9 +65,6 @@ // another process. Otherwise it is 0. virtual int GetOriginPID() const = 0; - // Unique identifier (within the scope of the child process) for this request. - virtual int GetRequestID() const = 0; - // The IPC route identifier of the RenderFrame. // TODO(jam): once all navigation and resource requests are sent between // frames and RenderView/RenderViewHost aren't involved we can remove this and
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc index ee7d0c5..16a4a6c 100644 --- a/content/public/common/url_constants.cc +++ b/content/public/common/url_constants.cc
@@ -31,7 +31,6 @@ const char kChromeUINetworkViewCacheHost[] = "view-http-cache"; const char kChromeUIResourcesHost[] = "resources"; const char kChromeUIServiceWorkerInternalsHost[] = "serviceworker-internals"; -const char kChromeUITcmallocHost[] = "tcmalloc"; const char kChromeUITracingHost[] = "tracing"; const char kChromeUIWebRTCInternalsHost[] = "webrtc-internals";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h index f20c3e3..03f5ff8 100644 --- a/content/public/common/url_constants.h +++ b/content/public/common/url_constants.h
@@ -39,7 +39,6 @@ CONTENT_EXPORT extern const char kChromeUINetworkViewCacheHost[]; CONTENT_EXPORT extern const char kChromeUIResourcesHost[]; CONTENT_EXPORT extern const char kChromeUIServiceWorkerInternalsHost[]; -CONTENT_EXPORT extern const char kChromeUITcmallocHost[]; CONTENT_EXPORT extern const char kChromeUITracingHost[]; CONTENT_EXPORT extern const char kChromeUIWebRTCInternalsHost[];
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index aa203aa..bca132d 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -67,6 +67,7 @@ "//ui/base", "//ui/events:dom_keycode_converter", "//ui/events:events_base", + "//ui/events/blink", "//ui/gl", "//ui/native_theme", "//ui/surface",
diff --git a/content/renderer/OWNERS b/content/renderer/OWNERS index b379b51e..c7ecacd 100644 --- a/content/renderer/OWNERS +++ b/content/renderer/OWNERS
@@ -2,6 +2,10 @@ per-file *.sb=set noparent per-file *.sb=rsesek@chromium.org -# DirectWrite specific changes +# DirectWrite specific changes. per-file renderer_font_platform_win.*=scottmg@chromium.org per-file renderer_font_platform_win.*=cpu@chromium.org + +# Web Notifications. +per-file notification_permission_dispatcher.*=mvanouwerkerk@chromium.org +per-file notification_permission_dispatcher.*=peter@chromium.org \ No newline at end of file
diff --git a/content/renderer/android/renderer_date_time_picker.cc b/content/renderer/android/renderer_date_time_picker.cc index 15b8332..7319c44 100644 --- a/content/renderer/android/renderer_date_time_picker.cc +++ b/content/renderer/android/renderer_date_time_picker.cc
@@ -5,18 +5,33 @@ #include "content/renderer/android/renderer_date_time_picker.h" #include "base/strings/string_util.h" +#include "content/common/date_time_suggestion.h" #include "content/common/view_messages.h" -#include "content/renderer/date_time_suggestion_builder.h" #include "content/renderer/render_view_impl.h" #include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h" #include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" #include "third_party/WebKit/public/web/WebDateTimeInputType.h" +#include "third_party/WebKit/public/web/WebDateTimeSuggestion.h" #include "ui/base/ime/text_input_type.h" using blink::WebString; namespace content { +namespace { + +// Converts a |blink::WebDateTimeSuggestion| structure to |DateTimeSuggestion|. +DateTimeSuggestion ToDateTimeSuggestion( + const blink::WebDateTimeSuggestion& suggestion) { + DateTimeSuggestion result; + result.value = suggestion.value; + result.localized_value = suggestion.localizedValue; + result.label = suggestion.label; + return result; +} + +} // namespace + static ui::TextInputType ToTextInputType(int type) { switch (type) { case blink::WebDateTimeInputTypeDate: @@ -64,7 +79,7 @@ message.step = chooser_params_.step; for (size_t i = 0; i < chooser_params_.suggestions.size(); i++) { message.suggestions.push_back( - DateTimeSuggestionBuilder::Build(chooser_params_.suggestions[i])); + ToDateTimeSuggestion(chooser_params_.suggestions[i])); } Send(new ViewHostMsg_OpenDateTimeDialog(routing_id(), message)); return true;
diff --git a/content/renderer/android/synchronous_compositor_filter.cc b/content/renderer/android/synchronous_compositor_filter.cc index 34cff90..edffd7e 100644 --- a/content/renderer/android/synchronous_compositor_filter.cc +++ b/content/renderer/android/synchronous_compositor_filter.cc
@@ -10,6 +10,7 @@ #include "content/common/android/sync_compositor_messages.h" #include "content/common/input_messages.h" #include "content/renderer/android/synchronous_compositor_proxy.h" +#include "ui/events/blink/synchronous_input_handler_proxy.h" namespace content { @@ -214,7 +215,7 @@ void SynchronousCompositorFilter::DidAddInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); DCHECK(synchronous_input_handler_proxy); Entry& entry = entry_map_[routing_id];
diff --git a/content/renderer/android/synchronous_compositor_filter.h b/content/renderer/android/synchronous_compositor_filter.h index bf7ba12..550bf1e 100644 --- a/content/renderer/android/synchronous_compositor_filter.h +++ b/content/renderer/android/synchronous_compositor_filter.h
@@ -13,6 +13,10 @@ #include "ipc/ipc_sender.h" #include "ipc/message_filter.h" +namespace ui { +class SynchronousInputHandlerProxy; +} + namespace content { class SynchronousCompositorProxy; @@ -54,7 +58,8 @@ void SetBoundHandler(const Handler& handler) override; void DidAddInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) override; + ui::SynchronousInputHandlerProxy* + synchronous_input_handler_proxy) override; void DidRemoveInputHandler(int routing_id) override; void DidOverscroll(int routing_id, const DidOverscrollParams& params) override; @@ -92,7 +97,7 @@ struct Entry { SynchronousCompositorExternalBeginFrameSource* begin_frame_source; SynchronousCompositorOutputSurface* output_surface; - SynchronousInputHandlerProxy* synchronous_input_handler_proxy; + ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy; Entry(); bool IsReady();
diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc index a6cf1e9d..7b829f9 100644 --- a/content/renderer/android/synchronous_compositor_output_surface.cc +++ b/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -164,8 +164,8 @@ gfx::Transform transform(gfx::Transform::kSkipInitialization); transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4. - surface_size_ = gfx::Size(canvas->getDeviceSize().width(), - canvas->getDeviceSize().height()); + surface_size_ = gfx::Size(canvas->getBaseLayerSize().width(), + canvas->getBaseLayerSize().height()); // Pass in the cached hw viewport and transform for tile priority to avoid // tile thrashing when the WebView is alternating between hardware and
diff --git a/content/renderer/android/synchronous_compositor_proxy.cc b/content/renderer/android/synchronous_compositor_proxy.cc index bd9fb355..d15f370dc 100644 --- a/content/renderer/android/synchronous_compositor_proxy.cc +++ b/content/renderer/android/synchronous_compositor_proxy.cc
@@ -18,7 +18,7 @@ IPC::Sender* sender, SynchronousCompositorOutputSurface* output_surface, SynchronousCompositorExternalBeginFrameSource* begin_frame_source, - SynchronousInputHandlerProxy* input_handler_proxy, + ui::SynchronousInputHandlerProxy* input_handler_proxy, InputHandlerManagerClient::Handler* handler) : routing_id_(routing_id), sender_(sender),
diff --git a/content/renderer/android/synchronous_compositor_proxy.h b/content/renderer/android/synchronous_compositor_proxy.h index 82341b65b..a91e9821 100644 --- a/content/renderer/android/synchronous_compositor_proxy.h +++ b/content/renderer/android/synchronous_compositor_proxy.h
@@ -10,7 +10,7 @@ #include "content/renderer/android/synchronous_compositor_external_begin_frame_source.h" #include "content/renderer/android/synchronous_compositor_output_surface.h" #include "content/renderer/input/input_handler_manager_client.h" -#include "content/renderer/input/synchronous_input_handler_proxy.h" +#include "ui/events/blink/synchronous_input_handler_proxy.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size_f.h" @@ -35,7 +35,7 @@ struct SyncCompositorDemandDrawHwParams; class SynchronousCompositorProxy - : public SynchronousInputHandler, + : public ui::SynchronousInputHandler, public SynchronousCompositorExternalBeginFrameSourceClient, public SynchronousCompositorOutputSurfaceClient { public: @@ -44,11 +44,11 @@ IPC::Sender* sender, SynchronousCompositorOutputSurface* output_surface, SynchronousCompositorExternalBeginFrameSource* begin_frame_source, - SynchronousInputHandlerProxy* input_handler_proxy, + ui::SynchronousInputHandlerProxy* input_handler_proxy, InputHandlerManagerClient::Handler* handler); ~SynchronousCompositorProxy() override; - // SynchronousInputHandler overrides. + // ui::SynchronousInputHandler overrides. void SetNeedsSynchronousAnimateInput() override; void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset, const gfx::ScrollOffset& max_scroll_offset, @@ -98,7 +98,7 @@ IPC::Sender* const sender_; SynchronousCompositorOutputSurface* const output_surface_; SynchronousCompositorExternalBeginFrameSource* const begin_frame_source_; - SynchronousInputHandlerProxy* const input_handler_proxy_; + ui::SynchronousInputHandlerProxy* const input_handler_proxy_; InputHandlerManagerClient::Handler* const input_handler_; bool inside_receive_;
diff --git a/content/renderer/date_time_suggestion_builder.cc b/content/renderer/date_time_suggestion_builder.cc deleted file mode 100644 index 7dff00d..0000000 --- a/content/renderer/date_time_suggestion_builder.cc +++ /dev/null
@@ -1,22 +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 "content/renderer/date_time_suggestion_builder.h" - -#include "content/common/date_time_suggestion.h" -#include "third_party/WebKit/public/web/WebDateTimeSuggestion.h" - -namespace content { - -// static -DateTimeSuggestion DateTimeSuggestionBuilder::Build( - const blink::WebDateTimeSuggestion& suggestion) { - DateTimeSuggestion result; - result.value = suggestion.value; - result.localized_value = suggestion.localizedValue; - result.label = suggestion.label; - return result; -} - -} // namespace content
diff --git a/content/renderer/date_time_suggestion_builder.h b/content/renderer/date_time_suggestion_builder.h deleted file mode 100644 index 5087051..0000000 --- a/content/renderer/date_time_suggestion_builder.h +++ /dev/null
@@ -1,23 +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 CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_ -#define CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_ - -namespace blink { -struct WebDateTimeSuggestion; -} // namespace blink - -namespace content { -struct DateTimeSuggestion; - -class DateTimeSuggestionBuilder { - public: - static DateTimeSuggestion Build( - const blink::WebDateTimeSuggestion& suggestion); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index a1c72bb1..0eb8bc0 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -331,8 +331,8 @@ settings.verify_property_trees = cmd->HasSwitch(cc::switches::kEnablePropertyTreeVerification); - if (cmd->HasSwitch(cc::switches::kDisableCompositorPropertyTrees)) - settings.use_property_trees = false; + settings.use_property_trees = + cmd->HasSwitch(cc::switches::kEnableCompositorPropertyTrees); settings.renderer_settings.allow_antialiasing &= !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing); // The means the renderer compositor has 2 possible modes:
diff --git a/content/renderer/input/input_event_filter.cc b/content/renderer/input/input_event_filter.cc index 6b648c7..0647685 100644 --- a/content/renderer/input/input_event_filter.cc +++ b/content/renderer/input/input_event_filter.cc
@@ -17,6 +17,7 @@ #include "content/public/common/content_switches.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" +#include "ui/events/blink/synchronous_input_handler_proxy.h" #include "ui/gfx/geometry/vector2d_f.h" using blink::WebInputEvent; @@ -57,7 +58,8 @@ void InputEventFilter::DidAddInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { + ui::SynchronousInputHandlerProxy* + synchronous_input_handler_proxy) { base::AutoLock locked(routes_lock_); routes_.insert(routing_id); }
diff --git a/content/renderer/input/input_event_filter.h b/content/renderer/input/input_event_filter.h index 2f87d57..e2d18f39 100644 --- a/content/renderer/input/input_event_filter.h +++ b/content/renderer/input/input_event_filter.h
@@ -20,8 +20,8 @@ class SingleThreadTaskRunner; } -namespace cc { -class InputHandler; +namespace ui { +class SynchronousInputHandlerProxy; } namespace IPC { @@ -39,8 +39,6 @@ namespace content { -class SynchronousInputHandlerProxy; - class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient, public IPC::MessageFilter { public: @@ -62,7 +60,8 @@ void SetBoundHandler(const Handler& handler) override; void DidAddInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_input_handler_proxy) override; + ui::SynchronousInputHandlerProxy* + synchronous_input_handler_proxy) override; void DidRemoveInputHandler(int routing_id) override; void DidOverscroll(int routing_id, const DidOverscrollParams& params) override;
diff --git a/content/renderer/input/input_handler_manager.cc b/content/renderer/input/input_handler_manager.cc index cbc9a15..85f229d2 100644 --- a/content/renderer/input/input_handler_manager.cc +++ b/content/renderer/input/input_handler_manager.cc
@@ -11,12 +11,14 @@ #include "base/trace_event/trace_event.h" #include "cc/input/input_handler.h" #include "components/scheduler/renderer/renderer_scheduler.h" +#include "content/common/input/web_input_event_traits.h" #include "content/renderer/input/input_event_filter.h" #include "content/renderer/input/input_handler_manager_client.h" #include "content/renderer/input/input_handler_wrapper.h" -#include "content/renderer/input/input_scroll_elasticity_controller.h" +#include "ui/events/blink/input_handler_proxy.h" using blink::WebInputEvent; +using ui::InputHandlerProxy; using scheduler::RendererScheduler; namespace content { @@ -137,6 +139,8 @@ const WebInputEvent* input_event, ui::LatencyInfo* latency_info) { DCHECK(task_runner_->BelongsToCurrentThread()); + TRACE_EVENT1("input,benchmark", "InputHandlerManager::HandleInputEvent", + "type", WebInputEventTraits::GetName(input_event->type)); auto it = input_handlers_.find(routing_id); if (it == input_handlers_.end()) { @@ -146,6 +150,8 @@ return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; } + TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent", + "result", "EventSentToInputHandlerProxy"); InputHandlerProxy* proxy = it->second->input_handler_proxy(); InputEventAckState input_event_ack_state = InputEventDispositionToAck( proxy->HandleInputEventWithLatencyInfo(*input_event, latency_info));
diff --git a/content/renderer/input/input_handler_manager_client.h b/content/renderer/input/input_handler_manager_client.h index 61cc5e6..9455af3 100644 --- a/content/renderer/input/input_handler_manager_client.h +++ b/content/renderer/input/input_handler_manager_client.h
@@ -24,9 +24,12 @@ class WebInputEvent; } +namespace ui { +class SynchronousInputHandlerProxy; +} + namespace content { struct DidOverscrollParams; -class SynchronousInputHandlerProxy; class CONTENT_EXPORT InputHandlerManagerClient { public: @@ -46,7 +49,7 @@ // Called from the compositor thread. virtual void DidAddInputHandler( int routing_id, - SynchronousInputHandlerProxy* synchronous_handler) = 0; + ui::SynchronousInputHandlerProxy* synchronous_handler) = 0; virtual void DidRemoveInputHandler(int routing_id) = 0; virtual void DidOverscroll(int routing_id, const DidOverscrollParams& params) = 0;
diff --git a/content/renderer/input/input_handler_wrapper.cc b/content/renderer/input/input_handler_wrapper.cc index d5596bdcc..5995d99b 100644 --- a/content/renderer/input/input_handler_wrapper.cc +++ b/content/renderer/input/input_handler_wrapper.cc
@@ -4,7 +4,10 @@ #include "content/renderer/input/input_handler_wrapper.h" +#include "base/command_line.h" #include "base/location.h" +#include "content/common/input/did_overscroll_params.h" +#include "content/public/common/content_switches.h" #include "content/renderer/input/input_event_filter.h" #include "content/renderer/input/input_handler_manager.h" #include "third_party/WebKit/public/platform/Platform.h" @@ -23,6 +26,9 @@ main_task_runner_(main_task_runner), render_view_impl_(render_view_impl) { DCHECK(input_handler); + input_handler_proxy_.set_smooth_scroll_enabled( + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableSmoothScrolling)); } InputHandlerWrapper::~InputHandlerWrapper() { @@ -47,7 +53,16 @@ deviceSource, velocity, cumulative_scroll); } -void InputHandlerWrapper::DidOverscroll(const DidOverscrollParams& params) { +void InputHandlerWrapper::DidOverscroll( + const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta, + const gfx::Vector2dF& current_fling_velocity, + const gfx::PointF& causal_event_viewport_point) { + DidOverscrollParams params; + params.accumulated_overscroll = accumulated_overscroll; + params.latest_overscroll_delta = latest_overscroll_delta; + params.current_fling_velocity = current_fling_velocity; + params.causal_event_viewport_point = causal_event_viewport_point; input_handler_manager_->DidOverscroll(routing_id_, params); }
diff --git a/content/renderer/input/input_handler_wrapper.h b/content/renderer/input/input_handler_wrapper.h index 5c925d051..69ff5c671 100644 --- a/content/renderer/input/input_handler_wrapper.h +++ b/content/renderer/input/input_handler_wrapper.h
@@ -8,13 +8,18 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "content/renderer/input/input_handler_manager.h" -#include "content/renderer/input/input_handler_proxy.h" -#include "content/renderer/input/input_handler_proxy_client.h" +#include "ui/events/blink/input_handler_proxy.h" +#include "ui/events/blink/input_handler_proxy_client.h" + +namespace ui { +class InputHandlerProxy; +class InputHandlerProxyClient; +} namespace content { // This class lives on the compositor thread. -class InputHandlerWrapper : public InputHandlerProxyClient { +class InputHandlerWrapper : public ui::InputHandlerProxyClient { public: InputHandlerWrapper( InputHandlerManager* input_handler_manager, @@ -25,7 +30,9 @@ ~InputHandlerWrapper() override; int routing_id() const { return routing_id_; } - InputHandlerProxy* input_handler_proxy() { return &input_handler_proxy_; } + ui::InputHandlerProxy* input_handler_proxy() { + return &input_handler_proxy_; + } // InputHandlerProxyClient implementation. void WillShutdown() override; @@ -35,14 +42,18 @@ blink::WebGestureDevice deviceSource, const blink::WebFloatPoint& velocity, const blink::WebSize& cumulativeScroll) override; - void DidOverscroll(const DidOverscrollParams& params) override; + void DidOverscroll( + const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta, + const gfx::Vector2dF& current_fling_velocity, + const gfx::PointF& causal_event_viewport_point) override; void DidStopFlinging() override; void DidAnimateForInput() override; private: InputHandlerManager* input_handler_manager_; int routing_id_; - InputHandlerProxy input_handler_proxy_; + ui::InputHandlerProxy input_handler_proxy_; scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; // Can only be accessed on the main thread.
diff --git a/content/renderer/notification_permission_dispatcher.cc b/content/renderer/notification_permission_dispatcher.cc index 90eef27..13f0ca3 100644 --- a/content/renderer/notification_permission_dispatcher.cc +++ b/content/renderer/notification_permission_dispatcher.cc
@@ -12,38 +12,38 @@ #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/modules/notifications/WebNotificationPermissionCallback.h" +using blink::WebNotificationPermissionCallback; + namespace content { NotificationPermissionDispatcher::NotificationPermissionDispatcher( - RenderFrame* render_frame) : RenderFrameObserver(render_frame) { -} + RenderFrame* render_frame) + : RenderFrameObserver(render_frame) {} -NotificationPermissionDispatcher::~NotificationPermissionDispatcher() { -} +NotificationPermissionDispatcher::~NotificationPermissionDispatcher() {} void NotificationPermissionDispatcher::RequestPermission( const blink::WebSecurityOrigin& origin, - blink::WebNotificationPermissionCallback* callback) { + WebNotificationPermissionCallback* callback) { if (!permission_service_.get()) { render_frame()->GetServiceRegistry()->ConnectToRemoteService( mojo::GetProxy(&permission_service_)); } - int request_id = pending_requests_.Add(callback); + scoped_ptr<WebNotificationPermissionCallback> owned_callback(callback); + // base::Unretained is safe here because the Mojo channel, with associated + // callbacks, will be deleted before the "this" instance is deleted. permission_service_->RequestPermission( - PERMISSION_NAME_NOTIFICATIONS, - origin.toString().utf8(), + PERMISSION_NAME_NOTIFICATIONS, origin.toString().utf8(), blink::WebUserGestureIndicator::isProcessingUserGesture(), base::Bind(&NotificationPermissionDispatcher::OnPermissionRequestComplete, - base::Unretained(this), - request_id)); + base::Unretained(this), base::Passed(owned_callback.Pass()))); } void NotificationPermissionDispatcher::OnPermissionRequestComplete( - int request_id, PermissionStatus status) { - blink::WebNotificationPermissionCallback* callback = - pending_requests_.Lookup(request_id); + scoped_ptr<WebNotificationPermissionCallback> callback, + PermissionStatus status) { DCHECK(callback); blink::WebNotificationPermission permission = @@ -61,7 +61,6 @@ } callback->permissionRequestComplete(permission); - pending_requests_.Remove(request_id); } } // namespace content
diff --git a/content/renderer/notification_permission_dispatcher.h b/content/renderer/notification_permission_dispatcher.h index 5c32693b..bb3430f 100644 --- a/content/renderer/notification_permission_dispatcher.h +++ b/content/renderer/notification_permission_dispatcher.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_RENDERER_NOTIFICATION_PERMISSION_DISPATCHER_H_ #define CONTENT_RENDERER_NOTIFICATION_PERMISSION_DISPATCHER_H_ -#include "base/id_map.h" +#include "base/memory/scoped_ptr.h" #include "content/common/permission_service.mojom.h" #include "content/public/renderer/render_frame_observer.h" @@ -16,6 +16,8 @@ namespace content { +class RenderFrame; + // Dispatcher for Web Notification permission requests. class NotificationPermissionDispatcher : public RenderFrameObserver { public: @@ -25,18 +27,13 @@ // Requests permission to display Web Notifications for |origin|. The callback // will be invoked when the permission status is available. This class will // take ownership of |callback|. - void RequestPermission( - const blink::WebSecurityOrigin& origin, - blink::WebNotificationPermissionCallback* callback); + void RequestPermission(const blink::WebSecurityOrigin& origin, + blink::WebNotificationPermissionCallback* callback); private: void OnPermissionRequestComplete( - int request_id, PermissionStatus status); - - // Tracks the active notification permission requests. This class takes - // ownership of the created WebNotificationPermissionCallback objects. - IDMap<blink::WebNotificationPermissionCallback, IDMapOwnPointer> - pending_requests_; + scoped_ptr<blink::WebNotificationPermissionCallback> callback, + PermissionStatus status); PermissionServicePtr permission_service_;
diff --git a/content/renderer/npapi/webplugin_delegate_proxy.cc b/content/renderer/npapi/webplugin_delegate_proxy.cc index edd39bd..054fa47d 100644 --- a/content/renderer/npapi/webplugin_delegate_proxy.cc +++ b/content/renderer/npapi/webplugin_delegate_proxy.cc
@@ -571,8 +571,10 @@ if (uses_shared_bitmaps_) { if (!front_buffer_canvas() || - (window_rect.width() != front_buffer_canvas()->getDevice()->width() || - window_rect.height() != front_buffer_canvas()->getDevice()->height())) + (window_rect.width() != + front_buffer_canvas()->getBaseLayerSize().width() || + window_rect.height() != + front_buffer_canvas()->getBaseLayerSize().height())) { bitmaps_changed = true; @@ -689,8 +691,7 @@ UpdateFrontBuffer(offset_rect, false); } - const SkBitmap& bitmap = - front_buffer_canvas()->getDevice()->accessBitmap(false); + const SkBitmap bitmap = skia::ReadPixels(front_buffer_canvas()); SkPaint paint; paint.setXfermodeMode( transparent_ ? SkXfermode::kSrcATop_Mode : SkXfermode::kSrc_Mode);
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 1fa92f3d..8c071c8 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -975,17 +975,6 @@ //------------------------------------------------------------------------------ -bool RendererBlinkPlatformImpl::processMemorySizesInBytes( - size_t* private_bytes, - size_t* shared_bytes) { - content::RenderThread::Get()->Send( - new RenderProcessHostMsg_GetProcessMemorySizes( - private_bytes, shared_bytes)); - return true; -} - -//------------------------------------------------------------------------------ - blink::WebGraphicsContext3D* RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D( const blink::WebGraphicsContext3D::Attributes& attributes) {
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index 247b97ce..74c8a57 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -141,8 +141,6 @@ blink::WebMediaRecorderHandler* createMediaRecorderHandler() override; blink::WebMediaStreamCenter* createMediaStreamCenter( blink::WebMediaStreamCenterClient* client) override; - bool processMemorySizesInBytes(size_t* private_bytes, - size_t* shared_bytes) override; blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D( const blink::WebGraphicsContext3D::Attributes& attributes) override; blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc index b6635053..d8f2d76 100644 --- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc +++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -109,7 +109,7 @@ std::set<BluetoothUUID> result; filter->GetUUIDs(result); return result; -}; +} // Notifies the adapter's observers that the services have been discovered. void NotifyServicesDiscovered(MockBluetoothAdapter* adapter, @@ -128,35 +128,35 @@ const std::string& fake_adapter_name) { if (fake_adapter_name == "BaseAdapter") return GetBaseAdapter(); - else if (fake_adapter_name == "NotPresentAdapter") + if (fake_adapter_name == "NotPresentAdapter") return GetNotPresentAdapter(); - else if (fake_adapter_name == "NotPoweredAdapter") + if (fake_adapter_name == "NotPoweredAdapter") return GetNotPoweredAdapter(); - else if (fake_adapter_name == "ScanFilterCheckingAdapter") + if (fake_adapter_name == "ScanFilterCheckingAdapter") return GetScanFilterCheckingAdapter(); - else if (fake_adapter_name == "EmptyAdapter") + if (fake_adapter_name == "EmptyAdapter") return GetEmptyAdapter(); - else if (fake_adapter_name == "FailStartDiscoveryAdapter") + if (fake_adapter_name == "FailStartDiscoveryAdapter") return GetFailStartDiscoveryAdapter(); - else if (fake_adapter_name == "GlucoseHeartRateAdapter") + if (fake_adapter_name == "GlucoseHeartRateAdapter") return GetGlucoseHeartRateAdapter(); - else if (fake_adapter_name == "UnicodeDeviceAdapter") + if (fake_adapter_name == "UnicodeDeviceAdapter") return GetUnicodeDeviceAdapter(); - else if (fake_adapter_name == "MissingServiceHeartRateAdapter") + if (fake_adapter_name == "MissingServiceHeartRateAdapter") return GetMissingServiceHeartRateAdapter(); - else if (fake_adapter_name == "MissingCharacteristicHeartRateAdapter") + if (fake_adapter_name == "MissingCharacteristicHeartRateAdapter") return GetMissingCharacteristicHeartRateAdapter(); - else if (fake_adapter_name == "HeartRateAdapter") + if (fake_adapter_name == "HeartRateAdapter") return GetHeartRateAdapter(); - else if (fake_adapter_name == "FailingConnectionsAdapter") + if (fake_adapter_name == "FailingConnectionsAdapter") return GetFailingConnectionsAdapter(); - else if (fake_adapter_name == "FailingGATTOperationsAdapter") + if (fake_adapter_name == "FailingGATTOperationsAdapter") return GetFailingGATTOperationsAdapter(); - else if (fake_adapter_name == "SecondDiscoveryFindsHeartRateAdapter") + if (fake_adapter_name == "SecondDiscoveryFindsHeartRateAdapter") return GetSecondDiscoveryFindsHeartRateAdapter(); - else if (fake_adapter_name == "DelayedServicesDiscoveryAdapter") + if (fake_adapter_name == "DelayedServicesDiscoveryAdapter") return GetDelayedServicesDiscoveryAdapter(); - else if (fake_adapter_name == "") + if (fake_adapter_name.empty()) return nullptr; if (base::StartsWith(fake_adapter_name, "PowerValueAdapter", @@ -194,7 +194,7 @@ } NOTREACHED() << fake_adapter_name; - return NULL; + return nullptr; } // Adapters @@ -697,7 +697,7 @@ // Write response. ON_CALL(*device_name, WriteRemoteCharacteristic(_, _, _)) - .WillByDefault(RunCallback<1 /* sucess callback */>()); + .WillByDefault(RunCallback<1 /* success callback */>()); generic_access->AddMockCharacteristic(device_name.Pass());
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index ec2bfca..674f7cf 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -862,3 +862,46 @@ "//ui/gl:test_support", ] } + +if (is_android) { + # TODO(GYP): Port Windows and ChromeOS logic. + test("video_decode_accelerator_unittest") { + deps = [ + "//base", + "//content", + "//media", + "//testing/gtest", + "//ui/base", + "//ui/gfx", + "//ui/gfx:test_support", + "//ui/gfx/geometry", + "//ui/gl", + "//ui/gl:test_support", + ] + configs += [ "//third_party/khronos:khronos_headers" ] + sources = [ + "//content/common/gpu/media/video_accelerator_unittest_helpers.h", + ] + if (is_android) { + sources += [ "//content/common/gpu/media/android_video_decode_accelerator_unittest.cc" ] + } else { + sources += [ + "//content/common/gpu/media/rendering_helper.cc", + "//content/common/gpu/media/rendering_helper.h", + "//content/common/gpu/media/video_decode_accelerator_unittest.cc", + ] + } + + if (is_android) { + deps += [ + "//gpu:test_support", + "//media/base/android", + "//testing/gmock", + ] + apk_deps = [ + "//media/base/android:media_java", + "//ui/android:ui_java", + ] + } + } +}
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index be21fc5..6e4d8bc 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -79,10 +79,14 @@ self.Fail('conformance2/buffers/uniform-buffers.html', bug=483282) self.Fail('conformance2/glsl3/array-complex-indexing.html', bug=483282) + self.Fail('conformance2/glsl3/const-array-init.html', + bug=1198) # angle bug ID self.Fail('conformance2/glsl3/forbidden-operators.html', bug=483282) self.Fail('conformance2/glsl3/invalid-default-precision.html', bug=483282) self.Fail('conformance2/glsl3/sequence-operator-returns-non-constant.html', bug=483282) + self.Fail('conformance2/extensions/promoted-extensions-in-shaders.html', + bug=295792) self.Fail('conformance2/reading/read-pixels-into-pixel-pack-buffer.html', bug=483282) self.Fail('conformance2/renderbuffers/framebuffer-test.html', bug=483282) @@ -90,7 +94,6 @@ bug=483282) self.Fail('conformance2/samplers/sampler-drawing-test.html', bug=483282) self.Skip('conformance2/textures/webgl_canvas/*', bug=483282) - self.Fail('conformance2/textures/misc/tex-mipmap-levels.html', bug=483282) self.Fail('conformance2/textures/misc/tex-storage-2d.html', bug=483282) # Windows only. @@ -116,6 +119,8 @@ ['win'], bug=483282) self.Fail('conformance2/textures/misc/tex-input-validation.html', ['win'], bug=483282) + self.Fail('conformance2/textures/misc/tex-mipmap-levels.html', + ['win'], bug=483282) self.Skip('conformance2/transform_feedback/transform_feedback.html', ['win'], bug=483282) # Windows 8 only. @@ -143,6 +148,31 @@ self.Fail('conformance2/textures/video/tex-image-and-sub-image-2d' + '-with-video-rgb5_a1-rgba-unsigned_byte.html', ['win8'], bug=483282) + self.Fail('conformance2/textures/video/tex-image-and-sub-image-3d' + + '-with-video-rgb5_a1-rgba-unsigned_byte.html', + ['win8'], bug=560555) + self.Fail('conformance2/textures/video/tex-image-and-sub-image-3d' + + '-with-video-rgb565-rgb-unsigned_byte.html', + ['win8'], bug=560555) + self.Fail('conformance2/textures/image_data/tex-image-and-sub-image-3d' + + '-with-image-data-rgb565-rgb-unsigned_byte.html', + ['win8'], bug=560555) + self.Fail('conformance2/textures/image_data/tex-image-and-sub-image-3d' + + '-with-image-data-rgb5_a1-rgba-unsigned_byte.html', + ['win8'], bug=560555) + self.Fail('conformance2/textures/image/tex-image-and-sub-image-3d' + + '-with-image-rgb5_a1-rgba-unsigned_byte.html', + ['win8'], bug=560555) + self.Fail('conformance2/textures/image/tex-image-and-sub-image-3d' + + '-with-image-rgb565-rgb-unsigned_byte.html', + ['win8'], bug=560555) + self.Fail('conformance2/textures/svg_image/tex-image-and-sub-image-3d' + + '-with-svg-image-rgb565-rgb-unsigned_byte.html', + ['win8'], bug=560555) + self.Fail('conformance2/textures/svg_image/tex-image-and-sub-image-3d' + + '-with-svg-image-rgb5_a1-rgba-unsigned_byte.html', + ['win8'], bug=560555) + # Windows Debug. Causing assertions in the GPU process which raise # a dialog box, so have to skip them rather than mark them as # failing. @@ -184,8 +214,6 @@ self.Fail('conformance2/textures/video/*', ['mac'], bug=483282) self.Fail('conformance2/textures/misc/gl-get-tex-parameter.html', ['mac'], bug=483282) - self.Fail('conformance2/textures/misc/tex-storage-compressed-formats.html', - ['mac'], bug=483282) self.Fail('conformance2/textures/misc/texture-npot.html', ['mac'], bug=483282) @@ -215,8 +243,9 @@ ['linux', 'amd'], bug=483282) self.Fail('conformance2/buffers/buffer-overflow-test.html', ['linux', 'amd'], bug=483282) - self.Fail('conformance2/textures/misc/tex-storage-compressed-formats.html', - ['linux', 'amd'], bug=483282) + self.Fail('conformance2/renderbuffers/framebuffer-texture-layer.html', + ['linux', 'amd'], bug=295792) + # Conflicting expectations to test that the # "Expectations Have No collisions" unittest works.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index da90b7d..7b114b3 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -38,8 +38,6 @@ bug=478572) self.Fail('conformance/extensions/ext-sRGB.html', bug=540900) - self.Fail('conformance/extensions/webgl-draw-buffers.html', - bug=559359) self.Fail('conformance/textures/misc/cube-incomplete-fbo.html', bug=559362) @@ -78,11 +76,13 @@ ['win', 'amd', 'd3d9'], bug=475095) # Win / D3D9 failures - # Skipping these tests because they're causing assertion failures. + # Skipping these two tests because they're causing assertion failures. self.Skip('conformance/extensions/oes-texture-float-with-canvas.html', ['win', 'd3d9'], bug=896) # angle bug ID self.Skip('conformance/extensions/oes-texture-half-float-with-canvas.html', ['win', 'd3d9'], bug=896) # angle bug ID + self.Fail('conformance/glsl/bugs/floor-div-cos-should-not-truncate.html', + ['win', 'd3d9'], bug=1179) # angle bug ID # WIN / D3D9 / Intel failures self.Fail('conformance/ogles/GL/cos/cos_001_to_006.html', @@ -221,8 +221,8 @@ # NVIDIA self.Fail('conformance/textures/misc/default-texture.html', ['linux', ('nvidia', 0x104a)], bug=422152) - self.Flaky('conformance/extensions/angle-instanced-arrays.html', - ['linux', 'nvidia'], bug=544989) + self.Fail('conformance/extensions/angle-instanced-arrays.html', + ['linux', 'nvidia'], bug=544989) # Too flaky to retry self.Flaky('conformance/extensions/oes-element-index-uint.html', ['linux', 'nvidia'], bug=524144) # AMD Radeon 5450
diff --git a/content/test/net/url_request_abort_on_end_job.cc b/content/test/net/url_request_abort_on_end_job.cc index f7ff5a9..6d237a8 100644 --- a/content/test/net/url_request_abort_on_end_job.cc +++ b/content/test/net/url_request_abort_on_end_job.cc
@@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/location.h" +#include "base/numerics/safe_conversions.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/thread_task_runner_handle.h" @@ -111,20 +112,16 @@ weak_factory_.GetWeakPtr())); } -bool URLRequestAbortOnEndJob::ReadRawData(net::IOBuffer* buf, - const int max_bytes, - int* bytes_read) { +int URLRequestAbortOnEndJob::ReadRawData(net::IOBuffer* buf, int max_bytes) { if (!sent_data_) { - *bytes_read = std::min(size_t(max_bytes), sizeof(kPageContent)); - std::memcpy(buf->data(), kPageContent, *bytes_read); + max_bytes = + std::min(max_bytes, base::checked_cast<int>(sizeof(kPageContent))); + std::memcpy(buf->data(), kPageContent, max_bytes); sent_data_ = true; - return true; + return max_bytes; } - SetStatus(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_CONNECTION_ABORTED)); - *bytes_read = -1; - return false; + return net::ERR_CONNECTION_ABORTED; } } // namespace content
diff --git a/content/test/net/url_request_abort_on_end_job.h b/content/test/net/url_request_abort_on_end_job.h index 88e348c..8a95533 100644 --- a/content/test/net/url_request_abort_on_end_job.h +++ b/content/test/net/url_request_abort_on_end_job.h
@@ -29,7 +29,7 @@ void Start() override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(net::HttpResponseInfo* info) override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; static void AddUrlHandler();
diff --git a/content/test/run_all_unittests.cc b/content/test/run_all_unittests.cc index 78d2c74..d4fbd200 100644 --- a/content/test/run_all_unittests.cc +++ b/content/test/run_all_unittests.cc
@@ -19,11 +19,11 @@ // Register JNI bindings for android. base::RegisterContentUriTestUtils(base::android::AttachCurrentThread()); #endif + content::UnitTestTestSuite test_suite( + new content::ContentTestSuite(argc, argv)); #if !defined(OS_IOS) content::InitializeMojo(); #endif - content::UnitTestTestSuite test_suite( - new content::ContentTestSuite(argc, argv)); return base::LaunchUnitTests( argc, argv, base::Bind(&content::UnitTestTestSuite::Run,
diff --git a/courgette/courgette.h b/courgette/courgette.h index bf6c925..49cf8b2 100644 --- a/courgette/courgette.h +++ b/courgette/courgette.h
@@ -93,7 +93,7 @@ // Detects the type of an executable file, and it's length. The length // may be slightly smaller than some executables (like ELF), but will include // all bytes the courgette algorithm has special benefit for. -// On sucess: +// On success: // Fill in type and detected_length, and return C_OK. // On failure: // Fill in type with UNKNOWN, detected_length with 0, and
diff --git a/crypto/symmetric_key_win.cc b/crypto/symmetric_key_win.cc index ec9cfa04..e2dc9b4 100644 --- a/crypto/symmetric_key_win.cc +++ b/crypto/symmetric_key_win.cc
@@ -38,7 +38,7 @@ NOTREACHED(); return 0; } -}; +} // Imports a raw/plaintext key of |key_size| stored in |*key_data| into a new // key created for the specified |provider|. |alg| contains the algorithm of @@ -83,7 +83,7 @@ CryptImportKey(provider, actual_key, actual_size, 0, flags, &unsafe_key); // Clean up the temporary copy of key, regardless of whether it was imported - // sucessfully or not. + // successfully or not. SecureZeroMemory(actual_key, actual_size); if (!ok)
diff --git a/docs/linux_faster_builds.md b/docs/linux_faster_builds.md index 625e0cfa..dd6285e4 100644 --- a/docs/linux_faster_builds.md +++ b/docs/linux_faster_builds.md
@@ -40,6 +40,10 @@ Icecc doesn't support clang yet. + use_sysroot=0 + +Icecc doesn't work with sysroot. + ## Build only specific targets If you specify just the target(s) you want built, the build will only walk that
diff --git a/docs/updating_clang.md b/docs/updating_clang.md index 529dc2b..d8a8575 100644 --- a/docs/updating_clang.md +++ b/docs/updating_clang.md
@@ -17,8 +17,9 @@ git cl try -m tryserver.chromium.linux -b linux_chromium_gn_dbg -b linux_chromium_chromeos_dbg_ng -b linux_chromium_asan_rel_ng -b linux_chromium_chromeos_asan_rel_ng -b android_clang_dbg_recipe -b - linux_chromium_trusty32_rel -b linux_chromium_rel_ng && git cl try -m - tryserver.blink -b linux_blink_rel` + linux_chromium_trusty32_rel -b linux_chromium_rel_ng -b + linux_chromium_msan_rel_ng && git cl try -m tryserver.blink -b + linux_blink_rel` 1. Commit roll CL from the first step 1. The bots will now pull the prebuilt binary, and goma will have a matching binary, too.
diff --git a/extensions/browser/api/socket/tcp_socket.cc b/extensions/browser/api/socket/tcp_socket.cc index 8d5257b4..79558d4 100644 --- a/extensions/browser/api/socket/tcp_socket.cc +++ b/extensions/browser/api/socket/tcp_socket.cc
@@ -196,8 +196,10 @@ } int result = server_socket_->ListenWithAddressAndPort(address, port, backlog); - if (result) + if (result) { + server_socket_.reset(); *error_msg = kSocketListenError; + } return result; }
diff --git a/gin/converter_unittest.cc b/gin/converter_unittest.cc index a7c3547..099895a 100644 --- a/gin/converter_unittest.cc +++ b/gin/converter_unittest.cc
@@ -80,7 +80,7 @@ struct { v8::Local<v8::Value> input; - bool expect_sucess; + bool expect_success; int expected_result; } test_data_from[] = { { Boolean::New(instance_->isolate(), false).As<Value>(), false, 0 }, @@ -102,7 +102,7 @@ int32_t result = std::numeric_limits<int32_t>::min(); bool success = Converter<int32_t>::FromV8(instance_->isolate(), test_data_from[i].input, &result); - EXPECT_EQ(test_data_from[i].expect_sucess, success) << i; + EXPECT_EQ(test_data_from[i].expect_success, success) << i; if (success) EXPECT_EQ(test_data_from[i].expected_result, result) << i; }
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt index a8af396..74f7632 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_path_rendering.txt
@@ -1027,7 +1027,8 @@ attached to a program object. Hence it is allowed to bind any name (except a name starting with "gl_") to an index, including a name that is never used as a varying in the fragment shader object. Assigned bindings for varying - variables that do not exist or are not active are ignored. + variables that do not exist or are not active are ignored. Using such bindings + behaves as if passed location was -1. It is possible for an application to bind more than one fragment input name to the same location. This is referred to as aliasing.
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 4b870d3..6897f0d2 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1998,16 +1998,6 @@ '5', ], }, - 'ZeroOnly': { - 'type': 'GLint', - 'is_complete': True, - 'valid': [ - '0', - ], - 'invalid': [ - '1', - ], - }, 'FalseOnly': { 'type': 'GLboolean', 'is_complete': True, @@ -2684,6 +2674,7 @@ 'FramebufferTexture2D': { 'decoder_func': 'DoFramebufferTexture2D', 'gl_test_func': 'glFramebufferTexture2DEXT', + 'unit_test': False, 'trace_level': 1, }, 'FramebufferTexture2DMultisampleEXT': {
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index d4693588..ce1d8b7 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -669,11 +669,12 @@ void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, - GLuint texture) { + GLuint texture, + GLint level) { gles2::cmds::FramebufferTexture2D* c = GetCmdSpace<gles2::cmds::FramebufferTexture2D>(); if (c) { - c->Init(target, attachment, textarget, texture); + c->Init(target, attachment, textarget, texture, level); } } @@ -2201,11 +2202,12 @@ GLenum attachment, GLenum textarget, GLuint texture, + GLint level, GLsizei samples) { gles2::cmds::FramebufferTexture2DMultisampleEXT* c = GetCmdSpace<gles2::cmds::FramebufferTexture2DMultisampleEXT>(); if (c) { - c->Init(target, attachment, textarget, texture, samples); + c->Init(target, attachment, textarget, texture, level, samples); } }
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index d6cac7e..4f818b6 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -715,12 +715,7 @@ << GLES2Util::GetStringAttachment(attachment) << ", " << GLES2Util::GetStringTextureTarget(textarget) << ", " << texture << ", " << level << ")"); - if (level != 0) { - SetGLError(GL_INVALID_VALUE, "glFramebufferTexture2D", - "level GL_INVALID_VALUE"); - return; - } - helper_->FramebufferTexture2D(target, attachment, textarget, texture); + helper_->FramebufferTexture2D(target, attachment, textarget, texture, level); CheckGLError(); } @@ -2949,18 +2944,13 @@ << GLES2Util::GetStringAttachment(attachment) << ", " << GLES2Util::GetStringTextureTarget(textarget) << ", " << texture << ", " << level << ", " << samples << ")"); - if (level != 0) { - SetGLError(GL_INVALID_VALUE, "glFramebufferTexture2DMultisampleEXT", - "level GL_INVALID_VALUE"); - return; - } if (samples < 0) { SetGLError(GL_INVALID_VALUE, "glFramebufferTexture2DMultisampleEXT", "samples < 0"); return; } helper_->FramebufferTexture2DMultisampleEXT(target, attachment, textarget, - texture, samples); + texture, level, samples); CheckGLError(); }
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 2788e4f1..23f6541 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -592,20 +592,13 @@ cmds::FramebufferTexture2D cmd; }; Cmds expected; - expected.cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 4); + expected.cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 4, 5); gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - 4, 0); + 4, 5); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -TEST_F(GLES2ImplementationTest, FramebufferTexture2DInvalidConstantArg4) { - gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - 4, 1); - EXPECT_TRUE(NoCommandsWritten()); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); -} - TEST_F(GLES2ImplementationTest, FramebufferTextureLayer) { struct Cmds { cmds::FramebufferTextureLayer cmd; @@ -2659,21 +2652,14 @@ cmds::FramebufferTexture2DMultisampleEXT cmd; }; Cmds expected; - expected.cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 4, 6); + expected.cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 4, 5, + 6); gl_->FramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, 4, 0, 6); + GL_TEXTURE_2D, 4, 5, 6); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -TEST_F(GLES2ImplementationTest, - FramebufferTexture2DMultisampleEXTInvalidConstantArg4) { - gl_->FramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, 4, 1, 6); - EXPECT_TRUE(NoCommandsWritten()); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); -} - TEST_F(GLES2ImplementationTest, TexStorage2DEXT) { struct Cmds { cmds::TexStorage2DEXT cmd;
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 0457731..de2a6f1 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -69,7 +69,7 @@ GL_APICALL void GL_APIENTRY glFinish (void); GL_APICALL void GL_APIENTRY glFlush (void); GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumRenderBufferTarget renderbuffertarget, GLidRenderbuffer renderbuffer); -GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumTextureTarget textarget, GLidTexture texture, GLintZeroOnly level); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumTextureTarget textarget, GLidTexture texture, GLint level); GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLidTexture texture, GLint level, GLint layer); GL_APICALL void GL_APIENTRY glFrontFace (GLenumFaceMode mode); GL_APICALL void GL_APIENTRY glGenBuffers (GLsizeiNotNegative n, GLuint* buffers); @@ -228,7 +228,7 @@ GL_APICALL void GL_APIENTRY glBlitFramebufferCHROMIUM (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenumBlitFilter filter); GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleCHROMIUM (GLenumRenderBufferTarget target, GLsizei samples, GLenumRenderBufferFormat internalformat, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenumRenderBufferTarget target, GLsizei samples, GLenumRenderBufferFormat internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumTextureTarget textarget, GLidTexture texture, GLintZeroOnly level, GLsizei samples); +GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumTextureTarget textarget, GLidTexture texture, GLint level, GLsizei samples); GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenumTextureBindTarget target, GLsizei levels, GLenumTextureInternalFormatStorage internalFormat, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizeiNotNegative n, GLuint* queries); GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizeiNotNegative n, const GLuint* queries);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index d30befc..01610ae 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -3229,21 +3229,24 @@ void Init(GLenum _target, GLenum _attachment, GLenum _textarget, - GLuint _texture) { + GLuint _texture, + GLint _level) { SetHeader(); target = _target; attachment = _attachment; textarget = _textarget; texture = _texture; + level = _level; } void* Set(void* cmd, GLenum _target, GLenum _attachment, GLenum _textarget, - GLuint _texture) { + GLuint _texture, + GLint _level) { static_cast<ValueType*>(cmd) - ->Init(_target, _attachment, _textarget, _texture); + ->Init(_target, _attachment, _textarget, _texture, _level); return NextCmdAddress<ValueType>(cmd); } @@ -3252,11 +3255,11 @@ uint32_t attachment; uint32_t textarget; uint32_t texture; - static const int32_t level = 0; + int32_t level; }; -static_assert(sizeof(FramebufferTexture2D) == 20, - "size of FramebufferTexture2D should be 20"); +static_assert(sizeof(FramebufferTexture2D) == 24, + "size of FramebufferTexture2D should be 24"); static_assert(offsetof(FramebufferTexture2D, header) == 0, "offset of FramebufferTexture2D header should be 0"); static_assert(offsetof(FramebufferTexture2D, target) == 4, @@ -3267,6 +3270,8 @@ "offset of FramebufferTexture2D textarget should be 12"); static_assert(offsetof(FramebufferTexture2D, texture) == 16, "offset of FramebufferTexture2D texture should be 16"); +static_assert(offsetof(FramebufferTexture2D, level) == 20, + "offset of FramebufferTexture2D level should be 20"); struct FramebufferTextureLayer { typedef FramebufferTextureLayer ValueType; @@ -10918,12 +10923,14 @@ GLenum _attachment, GLenum _textarget, GLuint _texture, + GLint _level, GLsizei _samples) { SetHeader(); target = _target; attachment = _attachment; textarget = _textarget; texture = _texture; + level = _level; samples = _samples; } @@ -10932,9 +10939,10 @@ GLenum _attachment, GLenum _textarget, GLuint _texture, + GLint _level, GLsizei _samples) { static_cast<ValueType*>(cmd) - ->Init(_target, _attachment, _textarget, _texture, _samples); + ->Init(_target, _attachment, _textarget, _texture, _level, _samples); return NextCmdAddress<ValueType>(cmd); } @@ -10943,12 +10951,12 @@ uint32_t attachment; uint32_t textarget; uint32_t texture; + int32_t level; int32_t samples; - static const int32_t level = 0; }; -static_assert(sizeof(FramebufferTexture2DMultisampleEXT) == 24, - "size of FramebufferTexture2DMultisampleEXT should be 24"); +static_assert(sizeof(FramebufferTexture2DMultisampleEXT) == 28, + "size of FramebufferTexture2DMultisampleEXT should be 28"); static_assert( offsetof(FramebufferTexture2DMultisampleEXT, header) == 0, "offset of FramebufferTexture2DMultisampleEXT header should be 0"); @@ -10965,8 +10973,11 @@ offsetof(FramebufferTexture2DMultisampleEXT, texture) == 16, "offset of FramebufferTexture2DMultisampleEXT texture should be 16"); static_assert( - offsetof(FramebufferTexture2DMultisampleEXT, samples) == 20, - "offset of FramebufferTexture2DMultisampleEXT samples should be 20"); + offsetof(FramebufferTexture2DMultisampleEXT, level) == 20, + "offset of FramebufferTexture2DMultisampleEXT level should be 20"); +static_assert( + offsetof(FramebufferTexture2DMultisampleEXT, samples) == 24, + "offset of FramebufferTexture2DMultisampleEXT samples should be 24"); struct TexStorage2DEXT { typedef TexStorage2DEXT ValueType;
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 683ae4d9..25d92e1 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -1018,9 +1018,9 @@ TEST_F(GLES2FormatTest, FramebufferTexture2D) { cmds::FramebufferTexture2D& cmd = *GetBufferAs<cmds::FramebufferTexture2D>(); - void* next_cmd = - cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLenum>(12), - static_cast<GLenum>(13), static_cast<GLuint>(14)); + void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), + static_cast<GLenum>(12), static_cast<GLenum>(13), + static_cast<GLuint>(14), static_cast<GLint>(15)); EXPECT_EQ(static_cast<uint32_t>(cmds::FramebufferTexture2D::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); @@ -1028,6 +1028,7 @@ EXPECT_EQ(static_cast<GLenum>(12), cmd.attachment); EXPECT_EQ(static_cast<GLenum>(13), cmd.textarget); EXPECT_EQ(static_cast<GLuint>(14), cmd.texture); + EXPECT_EQ(static_cast<GLint>(15), cmd.level); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } @@ -3696,9 +3697,10 @@ TEST_F(GLES2FormatTest, FramebufferTexture2DMultisampleEXT) { cmds::FramebufferTexture2DMultisampleEXT& cmd = *GetBufferAs<cmds::FramebufferTexture2DMultisampleEXT>(); - void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11), - static_cast<GLenum>(12), static_cast<GLenum>(13), - static_cast<GLuint>(14), static_cast<GLsizei>(15)); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLenum>(12), + static_cast<GLenum>(13), static_cast<GLuint>(14), + static_cast<GLint>(15), static_cast<GLsizei>(16)); EXPECT_EQ( static_cast<uint32_t>(cmds::FramebufferTexture2DMultisampleEXT::kCmdId), cmd.header.command); @@ -3707,7 +3709,8 @@ EXPECT_EQ(static_cast<GLenum>(12), cmd.attachment); EXPECT_EQ(static_cast<GLenum>(13), cmd.textarget); EXPECT_EQ(static_cast<GLuint>(14), cmd.texture); - EXPECT_EQ(static_cast<GLsizei>(15), cmd.samples); + EXPECT_EQ(static_cast<GLint>(15), cmd.level); + EXPECT_EQ(static_cast<GLsizei>(16), cmd.samples); CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index c01034a..af0a62f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4999,7 +4999,36 @@ if (workarounds().set_texture_filter_before_generating_mipmap) { glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); } + + // Workaround for Mac driver bug. If the base level is non-zero but the zero + // level of a texture has not been set glGenerateMipmaps sets the entire mip + // chain to opaque black. If the zero level is set at all, however, the mip + // chain is properly generated from the base level. + bool texture_zero_level_set = false; + GLenum type = 0; + GLenum internal_format = 0; + GLenum format = 0; + if (workarounds().set_zero_level_before_generating_mipmap && + target == GL_TEXTURE_2D) { + Texture* tex = texture_ref->texture(); + if (tex && tex->base_level() != 0 && + !tex->GetLevelType(target, 0, &type, &internal_format) && + tex->GetLevelType(target, tex->base_level(), &type, &internal_format)) { + format = TextureManager::ExtractFormatFromStorageFormat(internal_format); + glTexImage2D(target, 0, internal_format, 1, 1, 0, format, type, nullptr); + texture_zero_level_set = true; + } + } + glGenerateMipmapEXT(target); + + if (texture_zero_level_set) { + // This may have some unwanted side effects, but we expect command buffer + // validation to prevent you from doing anything weird with the texture + // after this, like calling texSubImage2D sucessfully. + glTexImage2D(target, 0, internal_format, 0, 0, 0, format, type, nullptr); + } + if (workarounds().set_texture_filter_before_generating_mipmap) { glTexParameteri(target, GL_TEXTURE_MIN_FILTER, texture_ref->texture()->min_filter()); @@ -6083,7 +6112,8 @@ service_id = texture_ref->service_id(); } - if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) { + if ((level > 0 && !feature_info_->IsES3Enabled()) || + !texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) { LOCAL_SET_GL_ERROR( GL_INVALID_VALUE, name, "level out of range"); @@ -15227,9 +15257,8 @@ } GLint location = static_cast<GLint>(c.location); - if (location == -1) { + if (program->IsInactiveFragmentInputLocationByFakeLocation(location)) return error::kNoError; - } const Program::FragmentInputInfo* fragment_input_info = program->GetFragmentInputInfoByFakeLocation(location);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc index 36b099ba4..aa9201d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
@@ -130,19 +130,6 @@ }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::FramebufferTexture2D, 0>( - bool valid) { - DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_, - kServiceFramebufferId); - if (valid) { - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - } -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::FramebufferTextureLayer, 0>( bool valid) { DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
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 dd93f8e..49cf5db8 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
@@ -827,38 +827,6 @@ EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } -TEST_P(GLES2DecoderTest1, FramebufferTexture2DValidArgs) { - EXPECT_CALL(*gl_, - FramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, kServiceTextureId, 0)); - SpecializedSetup<cmds::FramebufferTexture2D, 0>(true); - cmds::FramebufferTexture2D cmd; - cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs0_0) { - EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); - SpecializedSetup<cmds::FramebufferTexture2D, 0>(false); - cmds::FramebufferTexture2D cmd; - cmd.Init(GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs2_0) { - EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); - SpecializedSetup<cmds::FramebufferTexture2D, 0>(false); - cmds::FramebufferTexture2D cmd; - cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_PROXY_TEXTURE_CUBE_MAP, - client_texture_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); -} - TEST_P(GLES2DecoderTest1, FramebufferTextureLayerValidArgs) { EXPECT_CALL(*gl_, FramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
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 64a27582d..d4434186 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -1254,7 +1254,7 @@ .WillOnce(Return(error)) .RetiresOnSaturation(); cmds::FramebufferTexture2D cmd; - cmd.Init(target, attachment, textarget, texture_client_id); + cmd.Init(target, attachment, textarget, texture_client_id, level); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc index d6e5c94..ce6fbb8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
@@ -117,11 +117,130 @@ cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_); + client_texture_id_, + 0); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } +TEST_P(GLES3DecoderTest, FramebufferTexture2DWithNoBoundTarget) { + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); + FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + client_texture_id_, + 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, FramebufferTexture2DValidArgs) { + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, kServiceTextureId, 0)); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + client_texture_id_, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES3DecoderTest, FramebufferTexture2DValidArgs) { + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, kServiceTextureId, 1)); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + client_texture_id_, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, FramebufferTexture2DInvalidArgs0_0) { + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + client_texture_id_, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES3DecoderTest, FramebufferTexture2DInvalidArgs0_0) { + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + client_texture_id_, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderTest, FramebufferTexture2DInvalidArgs2_0) { + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_PROXY_TEXTURE_CUBE_MAP, + client_texture_id_, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES3DecoderTest, FramebufferTexture2DInvalidArgs2_0) { + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_PROXY_TEXTURE_CUBE_MAP, + client_texture_id_, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_P(GLES2DecoderTest, FramebufferTexture2DInvalidArgs4_0) { + EXPECT_CALL(*gl_, FramebufferTexture2DEXT(_, _, _, _, _)).Times(0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + client_texture_id_, 1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES3DecoderTest, FramebufferTexture2DValidArgs4_0) { + EXPECT_CALL(*gl_, + FramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, kServiceTextureId, 0)); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + cmds::FramebufferTexture2D cmd; + cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + client_texture_id_, 0); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_P(GLES2DecoderTest, GetFramebufferAttachmentParameterivWithNoBoundTarget) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -196,7 +315,8 @@ fbtex_cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_); + client_texture_id_, + 0); cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, @@ -1336,7 +1456,8 @@ fbtex_cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_); + client_texture_id_, + 0); EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc index 7c7cf7c9..58443ec 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
@@ -2957,7 +2957,8 @@ fbtex_cmd.Init(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - client_texture_id_); + client_texture_id_, + 0); EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError());
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index dc60003..bfff34c 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc
@@ -278,6 +278,7 @@ uniform_infos_.clear(); uniform_locations_.clear(); fragment_input_infos_.clear(); + fragment_input_locations_.clear(); sampler_indices_.clear(); attrib_location_to_index_map_.clear(); } @@ -663,11 +664,21 @@ void Program::UpdateFragmentInputs() { if (!feature_info().feature_flags().chromium_path_rendering) return; + for (const auto& binding : bind_fragment_input_location_map_) { + if (binding.second < 0) + continue; + size_t client_location = static_cast<size_t>(binding.second); + if (fragment_input_locations_.size() <= client_location) + fragment_input_locations_.resize(client_location + 1); + fragment_input_locations_[client_location].SetInactive(); + } + GLint num_fragment_inputs = 0; glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES, &num_fragment_inputs); if (num_fragment_inputs <= 0) return; + GLint max_len = 0; glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH, &max_len); @@ -680,6 +691,7 @@ const GLenum kQueryProperties[] = {GL_LOCATION, GL_TYPE, GL_ARRAY_SIZE}; + std::vector<size_t> client_location_indices; for (GLint ii = 0; ii < num_fragment_inputs; ++ii) { GLsizei name_length = 0; glGetProgramResourceName(service_id_, GL_FRAGMENT_INPUT_NV, ii, max_len, @@ -728,12 +740,9 @@ query_results[0] >= 0) { size_t client_location = static_cast<size_t>(it->second); GLuint service_location = static_cast<GLuint>(query_results[0]); - - if (fragment_input_infos_.size() <= client_location) - fragment_input_infos_.resize(client_location + 1); - DCHECK(!fragment_input_infos_[client_location].IsValid()); - fragment_input_infos_[client_location] = - FragmentInputInfo(type, service_location); + fragment_input_infos_.push_back( + FragmentInputInfo(type, service_location)); + client_location_indices.push_back(client_location); } if (size <= 1) @@ -762,15 +771,21 @@ GLint service_location = glGetProgramResourceLocation( service_id_, GL_FRAGMENT_INPUT_NV, service_element_name.c_str()); if (service_location >= 0) { - if (fragment_input_infos_.size() <= client_location) - fragment_input_infos_.resize(client_location + 1); - DCHECK(!fragment_input_infos_[client_location].IsValid()); - fragment_input_infos_[client_location] = - FragmentInputInfo(type, static_cast<GLuint>(service_location)); + fragment_input_infos_.push_back( + FragmentInputInfo(type, static_cast<GLuint>(service_location))); + client_location_indices.push_back(client_location); } } } } + for (size_t i = 0; i < client_location_indices.size(); ++i) { + size_t client_location = client_location_indices[i]; + // Before linking, we already validated that no two statically used fragment + // inputs are bound to the same location. + DCHECK(!fragment_input_locations_[client_location].IsActive()); + fragment_input_locations_[client_location].SetActive( + &fragment_input_infos_[i]); + } } void Program::ExecuteBindAttribLocationCalls() { @@ -1024,7 +1039,8 @@ if (!uniform_locations_[location_index].IsActive()) return nullptr; - const UniformInfo* info = uniform_locations_[location_index].uniform(); + const UniformInfo* info = + uniform_locations_[location_index].shader_variable(); size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); if (static_cast<GLsizei>(element_index) >= info->size) return nullptr; @@ -1085,13 +1101,24 @@ const Program::FragmentInputInfo* Program::GetFragmentInputInfoByFakeLocation( GLint fake_location) const { - if (fake_location < 0 || - static_cast<size_t>(fake_location) >= fragment_input_infos_.size()) + if (fake_location < 0) return nullptr; - const FragmentInputInfo* info = &fragment_input_infos_[fake_location]; - if (!info->IsValid()) + size_t location_index = static_cast<size_t>(fake_location); + if (location_index >= fragment_input_locations_.size()) return nullptr; - return info; + if (!fragment_input_locations_[location_index].IsActive()) + return nullptr; + return fragment_input_locations_[location_index].shader_variable(); +} + +bool Program::IsInactiveFragmentInputLocationByFakeLocation( + GLint fake_location) const { + if (fake_location < 0) + return true; + size_t location_index = static_cast<size_t>(fake_location); + if (location_index >= fragment_input_locations_.size()) + return false; + return fragment_input_locations_[location_index].IsInactive(); } bool Program::SetUniformLocationBinding( @@ -1227,7 +1254,7 @@ if (!uniform_locations_[location_index].IsActive()) return false; - UniformInfo* info = uniform_locations_[location_index].uniform(); + UniformInfo* info = uniform_locations_[location_index].shader_variable(); size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); if (static_cast<GLsizei>(element_index) >= info->size)
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index daecf4d..942659d 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h
@@ -66,7 +66,6 @@ FragmentInputInfo(GLenum _type, GLuint _location) : type(_type), location(_location) {} FragmentInputInfo() : type(GL_NONE), location(0) {} - bool IsValid() const { return type != GL_NONE; } GLenum type; GLuint location; }; @@ -107,39 +106,44 @@ std::string name; }; - class UniformLocationEntry { + template <typename T> + class ShaderVariableLocationEntry { public: - UniformLocationEntry() : uniform_(nullptr), inactive_(false) {} - bool IsUnused() const { return !uniform_ && !inactive_; } + ShaderVariableLocationEntry() + : shader_variable_(nullptr), inactive_(false) {} + bool IsUnused() const { return !shader_variable_ && !inactive_; } bool IsInactive() const { return inactive_; } - bool IsActive() const { return uniform_ != nullptr; } + bool IsActive() const { return shader_variable_ != nullptr; } void SetInactive() { - uniform_ = nullptr; + shader_variable_ = nullptr; inactive_ = true; } - void SetActive(UniformInfo* uniform) { - DCHECK(uniform); - uniform_ = uniform; + void SetActive(T* shader_variable) { + DCHECK(shader_variable); + shader_variable_ = shader_variable; inactive_ = false; } - const UniformInfo* uniform() const { + const T* shader_variable() const { DCHECK(IsActive()); - return uniform_; + return shader_variable_; } - UniformInfo* uniform() { + T* shader_variable() { DCHECK(IsActive()); - return uniform_; + return shader_variable_; } private: - UniformInfo* uniform_; // Pointer to uniform_info_ vector entry. + T* shader_variable_; // Pointer to *_info_ vector entry. bool inactive_; }; typedef std::vector<UniformInfo> UniformInfoVector; - typedef std::vector<UniformLocationEntry> UniformLocationVector; + typedef std::vector<ShaderVariableLocationEntry<UniformInfo>> + UniformLocationVector; typedef std::vector<VertexAttrib> AttribInfoVector; typedef std::vector<FragmentInputInfo> FragmentInputInfoVector; + typedef std::vector<ShaderVariableLocationEntry<FragmentInputInfo>> + FragmentInputLocationVector; typedef std::vector<int> SamplerIndices; typedef std::map<std::string, GLint> LocationMap; typedef std::vector<std::string> StringVector; @@ -192,6 +196,8 @@ const FragmentInputInfo* GetFragmentInputInfoByFakeLocation( GLint fake_location) const; + bool IsInactiveFragmentInputLocationByFakeLocation(GLint fake_location) const; + // Gets the fake location of a uniform by name. GLint GetUniformFakeLocation(const std::string& name) const; @@ -439,6 +445,7 @@ SamplerIndices sampler_indices_; FragmentInputInfoVector fragment_input_infos_; + FragmentInputLocationVector fragment_input_locations_; // The program this Program is tracking. GLuint service_id_;
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 7041311c..e743936 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -424,11 +424,12 @@ return CAN_RENDER_ALWAYS; if (target_ != GL_TEXTURE_EXTERNAL_OES) { - if (face_infos_.empty()) { + if (face_infos_.empty() || + static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) { return CAN_RENDER_NEVER; } - - const Texture::LevelInfo& first_face = face_infos_[0].level_infos[0]; + const Texture::LevelInfo& first_face = + face_infos_[0].level_infos[base_level_]; if (first_face.width == 0 || first_face.height == 0 || first_face.depth == 0) { @@ -531,7 +532,7 @@ } for (size_t ii = 0; ii < face_infos_.size(); ++ii) { const Texture::FaceInfo& face_info = face_infos_[ii]; - const Texture::LevelInfo& level0_info = face_info.level_infos[0]; + const Texture::LevelInfo& level0_info = face_info.level_infos[base_level_]; GLsizei width = level0_info.width; GLsizei height = level0_info.height; GLsizei depth = level0_info.depth; @@ -539,7 +540,8 @@ GLES2Util::IndexToGLFaceTarget(ii); const GLsizei num_mips = face_info.num_mip_levels; - for (GLsizei level = 1; level < num_mips; ++level) { + for (GLsizei level = base_level_ + 1; + level < base_level_ + num_mips; ++level) { width = std::max(1, width >> 1); height = std::max(1, height >> 1); depth = std::max(1, depth >> 1); @@ -639,9 +641,9 @@ return complete; } -bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face, +bool Texture::TextureMipComplete(const Texture::LevelInfo& base_level_face, GLenum target, - GLint level, + GLint level_diff, GLenum internal_format, GLsizei width, GLsizei height, @@ -649,17 +651,18 @@ GLenum format, GLenum type) { bool complete = (target != 0); - if (level != 0) { - const GLsizei mip_width = std::max(1, level0_face.width >> level); - const GLsizei mip_height = std::max(1, level0_face.height >> level); - const GLsizei mip_depth = std::max(1, level0_face.depth >> level); + if (level_diff > 0) { + const GLsizei mip_width = std::max(1, base_level_face.width >> level_diff); + const GLsizei mip_height = + std::max(1, base_level_face.height >> level_diff); + const GLsizei mip_depth = std::max(1, base_level_face.depth >> level_diff); complete &= (width == mip_width && height == mip_height && depth == mip_depth && - internal_format == level0_face.internal_format && - format == level0_face.format && - type == level0_face.type); + internal_format == base_level_face.internal_format && + format == base_level_face.format && + type == base_level_face.type); } return complete; } @@ -771,6 +774,41 @@ (*it)->manager()->IncFramebufferStateChangeCount(); } +void Texture::UpdateBaseLevel(GLint base_level) { + if (base_level_ == base_level) + return; + base_level_ = base_level; + + UpdateNumMipLevels(); +} + +void Texture::UpdateMaxLevel(GLint max_level) { + if (max_level_ == max_level) + return; + max_level_ = max_level; + + UpdateNumMipLevels(); +} + +void Texture::UpdateNumMipLevels() { + if (face_infos_.empty()) + return; + + for (size_t ii = 0; ii < face_infos_.size(); ++ii) { + Texture::FaceInfo& face_info = face_infos_[ii]; + if (static_cast<size_t>(base_level_) >= face_info.level_infos.size()) + continue; + const Texture::LevelInfo& info = face_info.level_infos[base_level_]; + face_info.num_mip_levels = std::min( + std::max(0, max_level_ - base_level_ + 1), + TextureManager::ComputeMipMapCount( + target_, info.width, info.height, info.depth)); + } + + // mipmap-completeness needs to be re-evaluated. + texture_mips_dirty_ = true; +} + void Texture::SetLevelInfo(const FeatureInfo* feature_info, GLenum target, GLint level, @@ -804,10 +842,11 @@ info.depth != depth || info.format != format || info.type != type) { - if (level == 0) { + if (level == base_level_) { // Calculate the mip level count. - face_infos_[face_index].num_mip_levels = - TextureManager::ComputeMipMapCount(target_, width, height, depth); + face_infos_[face_index].num_mip_levels = std::min( + std::max(0, max_level_ - base_level_ + 1), + TextureManager::ComputeMipMapCount(target_, width, height, depth)); // Update NPOT face count for the first level. bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth); @@ -837,7 +876,7 @@ estimated_size_ -= info.estimated_size; GLES2Util::ComputeImageDataSizes( - width, height, 1, format, type, 4, &info.estimated_size, NULL, NULL); + width, height, depth, format, type, 4, &info.estimated_size, NULL, NULL); estimated_size_ += info.estimated_size; max_level_set_ = std::max(max_level_set_, level); @@ -985,13 +1024,13 @@ if (param < 0) { return GL_INVALID_VALUE; } - base_level_ = param; + UpdateBaseLevel(param); break; case GL_TEXTURE_MAX_LEVEL: if (param < 0) { return GL_INVALID_VALUE; } - max_level_ = param; + UpdateMaxLevel(param); break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (param < 1) { @@ -1054,7 +1093,8 @@ // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0); - if (face_infos_.empty()) { + if (face_infos_.empty() || + static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) { texture_complete_ = false; cube_complete_ = false; return; @@ -1062,7 +1102,7 @@ // Update texture_complete and cube_complete status. const Texture::FaceInfo& first_face = face_infos_[0]; - const Texture::LevelInfo& first_level = first_face.level_infos[0]; + const Texture::LevelInfo& first_level = first_face.level_infos[base_level_]; const GLsizei levels_needed = first_face.num_mip_levels; texture_complete_ = @@ -1087,16 +1127,17 @@ bool texture_level0_complete = true; if (cube_complete_ && texture_level0_dirty_) { for (size_t ii = 0; ii < face_infos_.size(); ++ii) { - const Texture::LevelInfo& level0 = face_infos_[ii].level_infos[0]; + const Texture::LevelInfo& face_base_level = + face_infos_[ii].level_infos[base_level_]; if (!TextureFaceComplete(first_level, ii, - level0.target, - level0.internal_format, - level0.width, - level0.height, - level0.depth, - level0.format, - level0.type)) { + face_base_level.target, + face_base_level.internal_format, + face_base_level.width, + face_base_level.height, + face_base_level.depth, + face_base_level.format, + face_base_level.type)) { texture_level0_complete = false; break; } @@ -1110,12 +1151,14 @@ for (size_t ii = 0; ii < face_infos_.size() && texture_mips_complete; ++ii) { const Texture::FaceInfo& face_info = face_infos_[ii]; - const Texture::LevelInfo& level0 = face_info.level_infos[0]; + const Texture::LevelInfo& base_level_info = + face_info.level_infos[base_level_]; for (GLsizei jj = 1; jj < levels_needed; ++jj) { - const Texture::LevelInfo& level_info = face_infos_[ii].level_infos[jj]; - if (!TextureMipComplete(level0, + const Texture::LevelInfo& level_info = + face_infos_[ii].level_infos[base_level_ + jj]; + if (!TextureMipComplete(base_level_info, level_info.target, - jj, + jj, // level - base_level_ level_info.internal_format, level_info.width, level_info.height, @@ -1140,7 +1183,8 @@ for (size_t ii = 0; ii < face_infos_.size(); ++ii) { const Texture::FaceInfo& face_info = face_infos_[ii]; - for (GLint jj = 0; jj < face_info.num_mip_levels; ++jj) { + for (GLint jj = base_level_; + jj < base_level_ + face_info.num_mip_levels; ++jj) { const Texture::LevelInfo& info = face_info.level_infos[jj]; if (info.target != 0) { if (!ClearLevel(decoder, info.target, jj)) { @@ -1168,6 +1212,7 @@ bool Texture::IsLevelCleared(GLenum target, GLint level) const { size_t face_index = GLES2Util::GLTargetToFaceIndex(target); if (face_index >= face_infos_.size() || + level < base_level_ || level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) { return true; } @@ -1190,6 +1235,7 @@ DCHECK(decoder); size_t face_index = GLES2Util::GLTargetToFaceIndex(target); if (face_index >= face_infos_.size() || + level < base_level_ || level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) { return true; }
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 2ae2561..2f118de 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h
@@ -272,7 +272,9 @@ FaceInfo(); ~FaceInfo(); + // This is relative to base_level and max_level of a texture. GLsizei num_mip_levels; + // This contains slots for all levels starting at 0. std::vector<LevelInfo> level_infos; }; @@ -362,10 +364,11 @@ GLenum format, GLenum type); - // Returns true if texture mip level is complete relative to first level. - static bool TextureMipComplete(const Texture::LevelInfo& level0_face, + // Returns true if texture mip level is complete relative to base level. + // Note that level_diff = level - base_level. + static bool TextureMipComplete(const Texture::LevelInfo& base_level_face, GLenum target, - GLint level, + GLint level_diff, GLenum internal_format, GLsizei width, GLsizei height, @@ -418,6 +421,10 @@ // referencing this texture. void IncAllFramebufferStateChangeCount(); + void UpdateBaseLevel(GLint base_level); + void UpdateMaxLevel(GLint max_level); + void UpdateNumMipLevels(); + MailboxManager* mailbox_manager_; // Info about each face and level of texture.
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index dc01e7a1..4f026d12 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -47,12 +47,12 @@ class TextureManagerTest : public GpuServiceTest { public: - static const GLint kMaxTextureSize = 16; + static const GLint kMaxTextureSize = 32; static const GLint kMaxCubeMapTextureSize = 8; - static const GLint kMaxRectangleTextureSize = 16; - static const GLint kMaxExternalTextureSize = 16; + static const GLint kMaxRectangleTextureSize = 32; + static const GLint kMaxExternalTextureSize = 32; static const GLint kMax3DTextureSize = 256; - static const GLint kMax2dLevels = 5; + static const GLint kMax2dLevels = 6; static const GLint kMaxCubeMapLevels = 4; static const GLint kMaxExternalLevels = 1; static const bool kUseDefaultTextures = false; @@ -465,11 +465,11 @@ class TextureTestBase : public GpuServiceTest { public: - static const GLint kMaxTextureSize = 16; + static const GLint kMaxTextureSize = 32; static const GLint kMaxCubeMapTextureSize = 8; - static const GLint kMaxRectangleTextureSize = 16; + static const GLint kMaxRectangleTextureSize = 32; static const GLint kMax3DTextureSize = 256; - static const GLint kMax2dLevels = 5; + static const GLint kMax2dLevels = 6; static const GLint kMaxCubeMapLevels = 4; static const GLuint kClient1Id = 1; static const GLuint kService1Id = 11; @@ -684,6 +684,55 @@ EXPECT_FALSE(manager_->HaveUnrenderableTextures()); } +TEST_F(TextureTest, BaseLevel) { + manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); + Texture* texture = texture_ref_->texture(); + EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); + // Check Setting level 1 to POT + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); + SetParameter( + texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR); + EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); + EXPECT_TRUE(manager_->HaveUnrenderableTextures()); + SetParameter( + texture_ref_.get(), GL_TEXTURE_BASE_LEVEL, 1, GL_NO_ERROR); + EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); + EXPECT_FALSE(manager_->HaveUnrenderableTextures()); +} + +TEST_F(TextureTest, BaseLevelMaxLevel) { + manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); + Texture* texture = texture_ref_->texture(); + EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target()); + // Set up level 2, 3, 4. + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2, GL_RGBA, 8, 8, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 8)); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); + manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 4, GL_RGBA, 2, 2, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); + SetParameter( + texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR, + GL_NO_ERROR); + SetParameter( + texture_ref_.get(), GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_NO_ERROR); + EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); + EXPECT_TRUE(manager_->HaveUnrenderableTextures()); + SetParameter( + texture_ref_.get(), GL_TEXTURE_BASE_LEVEL, 2, GL_NO_ERROR); + EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); + EXPECT_TRUE(manager_->HaveUnrenderableTextures()); + SetParameter( + texture_ref_.get(), GL_TEXTURE_MAX_LEVEL, 4, GL_NO_ERROR); + EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); + EXPECT_FALSE(manager_->HaveUnrenderableTextures()); + SetParameter( + texture_ref_.get(), GL_TEXTURE_BASE_LEVEL, 0, GL_NO_ERROR); + EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); + EXPECT_TRUE(manager_->HaveUnrenderableTextures()); +} + TEST_F(TextureMemoryTrackerTest, MarkMipmapsGenerated) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 64);
diff --git a/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc b/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc index 4a05a6a..6243ea3 100644 --- a/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc +++ b/gpu/command_buffer/tests/gl_chromium_path_rendering_unittest.cc
@@ -1689,6 +1689,91 @@ TeardownStateForTestPattern(); } +TEST_P(CHROMIUMPathRenderingWithTexturingTest, UnusedFragmentInputUpdate) { + if (!IsApplicable()) + return; + + // clang-format off + static const char* kVertexShaderString = SHADER( + attribute vec4 a_position; + void main() { + gl_Position = a_position; + } + ); + static const char* kFragmentShaderString = SHADER( + precision mediump float; + uniform vec4 u_colorA; + uniform float u_colorU; + uniform vec4 u_colorC; + void main() { + gl_FragColor = u_colorA + u_colorC; + } + ); + // clang-format on + const GLint kColorULocation = 1; + const GLint kNonexistingLocation = 5; + const GLint kUnboundLocation = 6; + + GLuint vertex_shader = + GLTestHelper::LoadShader(GL_VERTEX_SHADER, kVertexShaderString); + GLuint fragment_shader = + GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShaderString); + GLuint program = glCreateProgram(); + glBindFragmentInputLocationCHROMIUM(program, kColorULocation, "u_colorU"); + // The non-existing uniform should behave like existing, but optimized away + // uniform. + glBindFragmentInputLocationCHROMIUM(program, kNonexistingLocation, + "nonexisting"); + // Let A and C be assigned automatic locations. + glAttachShader(program, vertex_shader); + glAttachShader(program, fragment_shader); + glLinkProgram(program); + GLint linked = 0; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + EXPECT_EQ(1, linked); + glUseProgram(program); + + GLfloat kColor[16] = { + 0.0f, + }; + // No errors on bound locations, since caller does not know + // if the driver optimizes them away or not. + glProgramPathFragmentInputGenCHROMIUM(program, kColorULocation, + GL_CONSTANT_CHROMIUM, 1, kColor); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // No errors on bound locations of names that do not exist + // in the shader. Otherwise it would be inconsistent wrt the + // optimization case. + glProgramPathFragmentInputGenCHROMIUM(program, kNonexistingLocation, + GL_CONSTANT_CHROMIUM, 1, kColor); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // The above are equal to updating -1. + glProgramPathFragmentInputGenCHROMIUM(program, -1, GL_CONSTANT_CHROMIUM, 1, + kColor); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // No errors when updating with other type either. + // The type can not be known with the non-existing case. + glProgramPathFragmentInputGenCHROMIUM(program, kColorULocation, + GL_CONSTANT_CHROMIUM, 4, kColor); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + glProgramPathFragmentInputGenCHROMIUM(program, kNonexistingLocation, + GL_CONSTANT_CHROMIUM, 4, kColor); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + glProgramPathFragmentInputGenCHROMIUM(program, -1, GL_CONSTANT_CHROMIUM, 4, + kColor); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); + + // Updating an unbound, non-existing location still causes + // an error. + glProgramPathFragmentInputGenCHROMIUM(program, kUnboundLocation, + GL_CONSTANT_CHROMIUM, 4, kColor); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); +} + INSTANTIATE_TEST_CASE_P(WithAndWithoutShaderNameMapping, CHROMIUMPathRenderingWithTexturingTest, ::testing::Bool());
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index e91ada8..31d7ee6 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "8.32", + "version": "8.33", "entries": [ { "id": 1, @@ -1591,11 +1591,22 @@ "type": "macosx" }, "vendor_id": "0x1002", - "device_id": ["0x9440", "0x944a"], + "device_id": ["0x9440", "0x944a", "0x9488", "0x9490"], "features": [ "disable_overlay_ca_layers", "disable_post_sub_buffers_for_onscreen_surfaces" ] + }, + { + "id": 136, + "description": "glGenerateMipmap fails if the zero texture level is not set on some Mac drivers", + "cr_bugs": [560499], + "os": { + "type": "macosx" + }, + "features": [ + "set_zero_level_before_generating_mipmap" + ] } ] }
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h index 88d3ffb..864627c4 100644 --- a/gpu/config/gpu_driver_bug_workaround_type.h +++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -146,6 +146,8 @@ wake_up_gpu_before_drawing) \ GPU_OP(UNBIND_EGL_CONTEXT_TO_FLUSH_DRIVER_CACHES, \ unbind_egl_context_to_flush_driver_caches) \ + GPU_OP(SET_ZERO_LEVEL_BEFORE_GENERATING_MIPMAP, \ + set_zero_level_before_generating_mipmap) \ namespace gpu {
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index 01674866..d2c0fde5 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -26,6 +26,9 @@ # chrome-eng-review per # https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/tour-of-the-chromium-buildbot?pli=1#TOC-Adding-new-build-configurations-and-tests-to-the-main-Chromium-waterfall-Commit-Queue try_job { + try_job_retry_config { + global_retry_quota: 1 + } buckets { name: "tryserver.chromium.linux" builders { name: "android_arm64_dbg_recipe" }
diff --git a/ios/chrome/browser/application_context_impl.cc b/ios/chrome/browser/application_context_impl.cc index e81f9be..4d6c8c1 100644 --- a/ios/chrome/browser/application_context_impl.cc +++ b/ios/chrome/browser/application_context_impl.cc
@@ -23,6 +23,7 @@ #include "components/network_time/network_time_tracker.h" #include "components/translate/core/browser/translate_download_manager.h" #include "components/variations/service/variations_service.h" +#include "components/web_resource/web_resource_pref_names.h" #include "ios/chrome/browser/chrome_paths.h" #include "ios/chrome/browser/history/history_service_factory.h" #include "ios/chrome/browser/pref_names.h" @@ -56,6 +57,8 @@ // static void ApplicationContextImpl::RegisterPrefs(PrefRegistrySimple* registry) { + registry->RegisterStringPref(ios::prefs::kApplicationLocale, std::string()); + registry->RegisterBooleanPref(prefs::kEulaAccepted, false); registry->RegisterBooleanPref(metrics::prefs::kMetricsReportingEnabled, false); registry->RegisterBooleanPref(prefs::kLastSessionExitedCleanly, true); @@ -85,12 +88,6 @@ variations::VariationsService* variations_service = GetVariationsService(); if (variations_service) variations_service->OnAppEnterForeground(); - - std::vector<ios::ChromeBrowserState*> loaded_browser_state = - GetChromeBrowserStateManager()->GetLoadedBrowserStates(); - for (ios::ChromeBrowserState* browser_state : loaded_browser_state) { - browser_state->SetExitType(ios::ChromeBrowserState::EXIT_CRASHED); - } } void ApplicationContextImpl::OnAppEnterBackground() { @@ -105,7 +102,6 @@ history_service->HandleBackgrounding(); } - browser_state->SetExitType(ios::ChromeBrowserState::EXIT_NORMAL); PrefService* browser_state_prefs = browser_state->GetPrefs(); if (browser_state_prefs) browser_state_prefs->CommitPendingWrite();
diff --git a/ios/chrome/browser/chrome_url_constants.cc b/ios/chrome/browser/chrome_url_constants.cc index f3e78909..f73a5fb 100644 --- a/ios/chrome/browser/chrome_url_constants.cc +++ b/ios/chrome/browser/chrome_url_constants.cc
@@ -54,9 +54,6 @@ const char kSyncGoogleDashboardURL[] = "https://www.google.com/settings/chrome/sync/"; -const char kPasswordManagerAccountDashboardURL[] = - "https://passwords.google.com/settings/passwords"; - const char kPageInfoHelpCenterURL[] = "https://support.google.com/chrome/?p=ui_security_indicator";
diff --git a/ios/chrome/browser/chrome_url_constants.h b/ios/chrome/browser/chrome_url_constants.h index 9a93b2b..9b314ff 100644 --- a/ios/chrome/browser/chrome_url_constants.h +++ b/ios/chrome/browser/chrome_url_constants.h
@@ -60,9 +60,6 @@ // URL to the sync google dashboard. extern const char kSyncGoogleDashboardURL[]; -// URL to the password manager account dashboard. -extern const char kPasswordManagerAccountDashboardURL[]; - // "What do these mean?" URL for the Page Info bubble. extern const char kPageInfoHelpCenterURL[];
diff --git a/ios/chrome/browser/find_in_page/find_in_page_controller.mm b/ios/chrome/browser/find_in_page/find_in_page_controller.mm index 1e18885..d6da2eb 100644 --- a/ios/chrome/browser/find_in_page/find_in_page_controller.mm +++ b/ios/chrome/browser/find_in_page/find_in_page_controller.mm
@@ -50,7 +50,7 @@ // |completionHandler| can be nil. - (void)startPumpingWithCompletionHandler:(ProceduralBlock)completionHandler; // Gives find in page more time to complete. Calls |completionHandler| with -// a BOOL indicating if the find operation was successfull. |completionHandler| +// a BOOL indicating if the find operation was successful. |completionHandler| // can be nil. - (void)pumpFindStringInPageWithCompletionHandler: (void (^)(BOOL))completionHandler;
diff --git a/ios/chrome/browser/find_in_page/js_findinpage_manager.h b/ios/chrome/browser/find_in_page/js_findinpage_manager.h index 77591ada..bc5b53a6 100644 --- a/ios/chrome/browser/find_in_page/js_findinpage_manager.h +++ b/ios/chrome/browser/find_in_page/js_findinpage_manager.h
@@ -47,7 +47,7 @@ completionHandler:(void (^)(BOOL, CGPoint))completionHandler; // Searches for more matches. Calls |completionHandler| with a success BOOL and -// scroll position if pumping was successfull. If the pumping was unsuccessfull +// scroll position if pumping was successful. If the pumping was unsuccessfull // another pumping call maybe required. |completionHandler| cannot be nil. // TODO(shreyasv): Consider folding the logic for re-pumping into this class // instead of having clients having to do it.
diff --git a/ios/chrome/browser/find_in_page/js_findinpage_manager.mm b/ios/chrome/browser/find_in_page/js_findinpage_manager.mm index 90766ff..9f411e28 100644 --- a/ios/chrome/browser/find_in_page/js_findinpage_manager.mm +++ b/ios/chrome/browser/find_in_page/js_findinpage_manager.mm
@@ -60,7 +60,7 @@ - (BOOL)processFindInPageResult:(NSString*)result scrollPosition:(CGPoint*)point; // Updates find in page model with results. Calls |completionHandler| with the -// the result of the processing and the new scroll position if successfull. If +// the result of the processing and the new scroll position if successful. If // |completionHandler| is called with NO, further pumping is required. // |completionHandler| cannot be nil. - (void)processFindInPagePumpResult:(NSString*)result
diff --git a/ios/chrome/browser/ios_chrome_io_thread.cc b/ios/chrome/browser/ios_chrome_io_thread.cc index 4fdb168c..c914b195 100644 --- a/ios/chrome/browser/ios_chrome_io_thread.cc +++ b/ios/chrome/browser/ios_chrome_io_thread.cc
@@ -395,7 +395,7 @@ globals_->transport_security_state.reset(new net::TransportSecurityState()); - std::vector<scoped_refptr<net::CTLogVerifier>> ct_logs( + std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs( net::ct::CreateLogVerifiersForKnownLogs()); net::MultiLogCTVerifier* ct_verifier = new net::MultiLogCTVerifier();
diff --git a/ios/chrome/browser/pref_names.cc b/ios/chrome/browser/pref_names.cc index 350cee0..c25c915 100644 --- a/ios/chrome/browser/pref_names.cc +++ b/ios/chrome/browser/pref_names.cc
@@ -14,6 +14,7 @@ const char kAcceptLanguages[] = "intl.accept_languages"; const char kAllowDeletingBrowserHistory[] = "history.deleting_enabled"; +const char kApplicationLocale[] = "intl.app_locale"; const char kBrowserStateInfoCache[] = "profile.info_cache"; const char kBrowserStateLastUsed[] = "profile.last_used"; const char kBrowserStatesLastActive[] = "profile.last_active_profiles";
diff --git a/ios/chrome/browser/pref_names.h b/ios/chrome/browser/pref_names.h index 9509471..7c2572e 100644 --- a/ios/chrome/browser/pref_names.h +++ b/ios/chrome/browser/pref_names.h
@@ -12,6 +12,7 @@ // Non-shared preferences should be in the prefs:: namespace (no ios::). extern const char kAcceptLanguages[]; extern const char kAllowDeletingBrowserHistory[]; +extern const char kApplicationLocale[]; extern const char kBrowserStateInfoCache[]; extern const char kBrowserStateLastUsed[]; extern const char kBrowserStatesLastActive[];
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index 017eb4e..7e61b40 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -8,7 +8,6 @@ #include "components/autofill/core/browser/autofill_manager.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #include "components/dom_distiller/core/distilled_page_prefs.h" #include "components/enhanced_bookmarks/bookmark_server_cluster_service.h" #include "components/gcm_driver/gcm_channel_status_syncer.h" @@ -67,11 +66,6 @@ [OmniboxGeolocationLocalState registerLocalState:registry]; [MemoryDebuggerManager registerLocalState:registry]; - // TODO(crbug.com/557814): data_reduction_proxy::prefs::kDataReductionProxy - // should be registered by data_reduction_proxy::RegisterPrefs() instead of - // here. - registry->RegisterStringPref(data_reduction_proxy::prefs::kDataReductionProxy, - std::string()); data_reduction_proxy::RegisterPrefs(registry); // TODO(shreyasv): Remove this in M49 as almost all users would have the
diff --git a/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h b/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h index db0772f..5a8b084a 100644 --- a/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h +++ b/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h
@@ -31,11 +31,6 @@ // This class is a Chrome-specific extension of the BrowserState interface. class ChromeBrowserState : public web::BrowserState { public: - enum ExitType { - EXIT_NORMAL, - EXIT_CRASHED, - }; - ~ChromeBrowserState() override {} // Returns the ChromeBrowserState corresponding to the given BrowserState. @@ -75,18 +70,6 @@ // a syncable_prefs::PrefServiceSyncable. virtual syncable_prefs::PrefServiceSyncable* GetSyncablePrefs() = 0; - // Sets the ExitType for the ChromeBrowserState. This may be invoked multiple - // times during shutdown; only the first such change (the transition from - // EXIT_CRASHED to one of the other values) is written to prefs, any later - // calls are ignored. - // - // NOTE: this is invoked internally on a normal shutdown, but is public so - // that it can be invoked to handle backgrounding/foregrounding. - virtual void SetExitType(ExitType exit_type) = 0; - - // Returns how the last session was shutdown. - virtual ExitType GetLastSessionExitType() = 0; - // Deletes all network related data since |time|. It deletes transport // security state since |time| and it also deletes HttpServerProperties data. // Works asynchronously, however if the |completion| callback is non-null, it
diff --git a/ios/web/crw_browsing_data_store_unittest.mm b/ios/web/crw_browsing_data_store_unittest.mm index 8db9898..f00421d 100644 --- a/ios/web/crw_browsing_data_store_unittest.mm +++ b/ios/web/crw_browsing_data_store_unittest.mm
@@ -153,7 +153,7 @@ EXPECT_EQ(0U, [observer modeChangeCount]); __block int callbacks_received_count = 0; - void (^unsucessfullCallback)(BOOL) = ^(BOOL success) { + void (^unsuccessfullCallback)(BOOL) = ^(BOOL success) { ASSERT_TRUE([NSThread isMainThread]); ++callbacks_received_count; BrowsingDataStoreMode mode = [browsing_data_store_ mode]; @@ -163,20 +163,20 @@ [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) { EXPECT_EQ(0, callbacks_received_count); - unsucessfullCallback(success); + unsuccessfullCallback(success); }]; EXPECT_EQ(CHANGING, [browsing_data_store_ mode]); EXPECT_EQ(1U, [observer modeChangeCount]); [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) { EXPECT_EQ(1, callbacks_received_count); - unsucessfullCallback(success); + unsuccessfullCallback(success); }]; EXPECT_EQ(CHANGING, [browsing_data_store_ mode]); [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) { EXPECT_EQ(2, callbacks_received_count); - unsucessfullCallback(success); + unsuccessfullCallback(success); }]; EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
diff --git a/ios/web/net/crw_cert_verification_controller.mm b/ios/web/net/crw_cert_verification_controller.mm index 42d3738..a2036dd 100644 --- a/ios/web/net/crw_cert_verification_controller.mm +++ b/ios/web/net/crw_cert_verification_controller.mm
@@ -18,7 +18,6 @@ #include "ios/web/public/web_thread.h" #import "ios/web/web_state/wk_web_view_security_util.h" #include "net/cert/cert_verify_result.h" -#include "net/ssl/ssl_config_service.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" @@ -430,8 +429,9 @@ web::CertVerifierBlockAdapter::Params params( blockCert.Pass(), base::SysNSStringToUTF8(host)); params.flags = self.certVerifyFlags; - params.crl_set = net::SSLConfigService::GetCRLSet(); // OCSP response is not provided by iOS API. + // CRLSets are not used, as the OS is used to make load/no-load + // decisions, not the CertVerifier. _certVerifier->Verify(params, ^(net::CertVerifyResult result, int) { completionHandler(result, YES); });
diff --git a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm index c1be1737..34061740 100644 --- a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm +++ b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm
@@ -212,6 +212,9 @@ // YES if the user has interacted with the content area since the last URL // change. BOOL _interactionRegisteredSinceLastURLChange; + + // YES if the web process backing _wkWebView is believed to currently be dead. + BOOL _webProcessIsDead; } // Dictionary where keys are the names of WKWebView properties and values are @@ -878,6 +881,7 @@ } - (void)webViewWebProcessDidCrash { + _webProcessIsDead = YES; if ([self.delegate respondsToSelector: @selector(webControllerWebProcessDidCrash:)]) { [self.delegate webControllerWebProcessDidCrash:self]; @@ -1469,6 +1473,13 @@ } - (void)webViewTitleDidChange { + // WKWebView's title becomes empty when the web process dies; ignore that + // update. + if (_webProcessIsDead) { + DCHECK_EQ(self.title.length, 0U); + return; + } + if ([self.delegate respondsToSelector: @selector(webController:titleDidChange:)]) { DCHECK(self.title); @@ -1541,6 +1552,7 @@ decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler: (void (^)(WKNavigationActionPolicy))decisionHandler { + _webProcessIsDead = NO; if (self.isBeingDestroyed) { decisionHandler(WKNavigationActionPolicyCancel); return;
diff --git a/ios/web/webui/url_data_manager_ios_backend.cc b/ios/web/webui/url_data_manager_ios_backend.cc index cc3e3e9..d5117c2 100644 --- a/ios/web/webui/url_data_manager_ios_backend.cc +++ b/ios/web/webui/url_data_manager_ios_backend.cc
@@ -96,7 +96,7 @@ // net::URLRequestJob implementation. void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; bool GetMimeType(std::string* mime_type) const override; int GetResponseCode() const override; void GetResponseInfo(net::HttpResponseInfo* info) override; @@ -142,7 +142,7 @@ // Do the actual copy from data_ (the data we're serving) into |buf|. // Separate from ReadRawData so we can handle async I/O. - void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read); + int CompleteRead(net::IOBuffer* buf, int buf_size); // The actual data we're serving. NULL until it's been fetched. scoped_refptr<base::RefCountedMemory> data_; @@ -291,58 +291,46 @@ void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); if (bytes) { - // The request completed, and we have all the data. - // Clear any IO pending status. - SetStatus(net::URLRequestStatus()); - data_ = bytes; - int bytes_read; if (pending_buf_.get()) { CHECK(pending_buf_->data()); - CompleteRead(pending_buf_.get(), pending_buf_size_, &bytes_read); + int rv = CompleteRead(pending_buf_.get(), pending_buf_size_); pending_buf_ = NULL; - NotifyReadComplete(bytes_read); + ReadRawDataComplete(rv); } } else { - // The request failed. - NotifyDone( - net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); + ReadRawDataComplete(net::ERR_FAILED); } } -bool URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { if (!data_.get()) { - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); DCHECK(!pending_buf_.get()); CHECK(buf->data()); pending_buf_ = buf; pending_buf_size_ = buf_size; - return false; // Tell the caller we're still waiting for data. + return net::ERR_IO_PENDING; // Tell the caller we're still waiting for + // data. } // Otherwise, the data is available. - CompleteRead(buf, buf_size, bytes_read); - return true; + return CompleteRead(buf, buf_size); } -void URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, - int buf_size, - int* bytes_read) { +int URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size) { // http://crbug.com/373841 char url_buf[128]; base::strlcpy(url_buf, request_->url().spec().c_str(), arraysize(url_buf)); base::debug::Alias(url_buf); - int remaining = static_cast<int>(data_->size()) - data_offset_; + int remaining = data_->size() - data_offset_; if (buf_size > remaining) buf_size = remaining; if (buf_size > 0) { memcpy(buf->data(), data_->front() + data_offset_, buf_size); data_offset_ += buf_size; } - *bytes_read = buf_size; + return buf_size; } namespace {
diff --git a/ipc/attachment_broker_mac_unittest.cc b/ipc/attachment_broker_mac_unittest.cc index 2e370cd..9e2a995a 100644 --- a/ipc/attachment_broker_mac_unittest.cc +++ b/ipc/attachment_broker_mac_unittest.cc
@@ -5,6 +5,7 @@ #include "build/build_config.h" #include <fcntl.h> +#include <mach/mach_vm.h> #include <sys/mman.h> #include "base/command_line.h" @@ -12,8 +13,12 @@ #include "base/files/scoped_file.h" #include "base/files/scoped_temp_dir.h" #include "base/mac/mac_util.h" +#include "base/mac/mach_logging.h" #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" +#include "base/strings/string_number_conversions.h" +#include "base/synchronization/spin_wait.h" +#include "base/time/time.h" #include "ipc/attachment_broker_messages.h" #include "ipc/attachment_broker_privileged_mac.h" #include "ipc/attachment_broker_unprivileged_mac.h" @@ -30,6 +35,14 @@ const char kDataBuffer3[] = "Two green bears but not a potato."; const char kDataBuffer4[] = "Red potato is best potato."; const std::string g_service_switch_name = "service_name"; +const size_t g_large_message_size = 8 * 1024 * 1024; +const int g_large_message_count = 1000; +const size_t g_medium_message_size = 512 * 1024; + +// Running the message loop is expected to increase the number of resident +// pages. The exact amount is non-deterministic, but for a simple test suite +// like this one, the increase is expected to be less than 1 MB. +const size_t g_expected_memory_increase = 1024 * 1024; enum TestResult { RESULT_UNKNOWN, @@ -37,6 +50,16 @@ RESULT_FAILURE, }; +mach_vm_size_t GetResidentSize() { + task_basic_info_64 info; + mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; + kern_return_t kr = task_info(mach_task_self(), TASK_BASIC_INFO_64, + reinterpret_cast<task_info_t>(&info), &count); + MACH_CHECK(kr == KERN_SUCCESS, kr) << "Couldn't get resident size."; + + return info.resident_size; +} + base::mac::ScopedMachSendRight GetMachPortFromBrokeredAttachment( const scoped_refptr<IPC::BrokerableAttachment>& attachment) { if (attachment->GetType() != @@ -418,6 +441,9 @@ void FinalCleanUp() { // There should be no leaked names. + SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE( + base::TimeDelta::FromSeconds(10), + active_names_at_start_ == IPC::GetActiveNameCount()); EXPECT_EQ(active_names_at_start_, IPC::GetActiveNameCount()); // Close the channel so the client's OnChannelError() gets fired. @@ -481,6 +507,12 @@ // destroyed. scoped_ptr<IPC::AttachmentBrokerPrivilegedMac> broker; base::mac::ScopedMachSendRight server_task_port; + + // Total resident memory before running the message loop. + mach_vm_size_t initial_resident_size; + + // Whether to emit log statements while processing messages. + bool message_logging; }; using OnMessageReceivedCallback = void (*)(IPC::Sender* sender, @@ -510,6 +542,7 @@ new IPC::AttachmentBrokerPrivilegedMac(&globals->port_provider)); globals->port_provider.InsertEntry(getppid(), server_task_port.get()); globals->server_task_port.reset(server_task_port.release()); + globals->message_logging = true; return globals; } @@ -528,17 +561,22 @@ globals->broker->RegisterCommunicationChannel(channel.get()); CHECK(channel->Connect()); + globals->initial_resident_size = GetResidentSize(); + while (true) { - LOG(INFO) << "Privileged process spinning run loop."; + if (globals->message_logging) + LOG(INFO) << "Privileged process spinning run loop."; base::MessageLoop::current()->Run(); ProxyListener::Reason reason = listener.get_reason(); if (reason == ProxyListener::CHANNEL_ERROR) break; while (listener.has_message()) { - LOG(INFO) << "Privileged process running callback."; + if (globals->message_logging) + LOG(INFO) << "Privileged process running callback."; callback(channel.get(), listener.get_first_message(), globals.get()); - LOG(INFO) << "Privileged process finishing callback."; + if (globals->message_logging) + LOG(INFO) << "Privileged process finishing callback."; listener.pop_first_message(); } } @@ -1152,4 +1190,143 @@ "SendSharedMemoryHandleToSelfDelayedPort"); } +// Tests the memory usage characteristics of attachment brokering a single large +// message. This test has the *potential* to be flaky, since it compares +// resident memory at different points in time, and that measurement is +// non-deterministic. +TEST_F(IPCAttachmentBrokerMacTest, MemoryUsageLargeMessage) { + // Mach-based SharedMemory isn't support on OSX 10.6. + if (base::mac::IsOSSnowLeopard()) + return; + + CommonSetUp("MemoryUsageLargeMessage"); + + std::string test_string(g_large_message_size, 'a'); + SendMessage1(test_string); + base::MessageLoop::current()->Run(); + CommonTearDown(); +} + +void MemoryUsageLargeMessageCallback(IPC::Sender* sender, + const IPC::Message& message, + ChildProcessGlobals* globals) { + EXPECT_LE(GetResidentSize(), + globals->initial_resident_size + g_expected_memory_increase); + + base::SharedMemoryHandle shm(GetSharedMemoryHandleFromMsg1(message)); + scoped_ptr<base::SharedMemory> shared_memory( + MapSharedMemoryHandle(shm, false)); + EXPECT_LE(GetResidentSize(), + globals->initial_resident_size + g_expected_memory_increase); + + char* addr = static_cast<char*>(shared_memory->memory()); + for (size_t i = 0; i < g_large_message_size; i += 1024) { + addr[i] = 'a'; + } + EXPECT_GE(GetResidentSize(), + globals->initial_resident_size + g_large_message_size); + + shared_memory.reset(); +#if !defined(ADDRESS_SANITIZER) && !defined(LEAK_SANITIZER) && \ + !defined(MEMORY_SANITIZER) && !defined(THREAD_SANITIZER) && \ + !defined(UNDEFINED_SANITIZER) + // Under a sanitizer build, releasing memory does not necessarily reduce the + // amount of resident memory. + EXPECT_LE(GetResidentSize(), + globals->initial_resident_size + g_expected_memory_increase); +#endif + + SendControlMessage(sender, true); +} + +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(MemoryUsageLargeMessage) { + return CommonPrivilegedProcessMain(&MemoryUsageLargeMessageCallback, + "MemoryUsageLargeMessage"); +} + +// Tests the memory usage characteristics of attachment brokering many small +// messages. This test has the *potential* to be flaky, since it compares +// resident memory at different points in time, and that measurement is +// non-deterministic. +TEST_F(IPCAttachmentBrokerMacTest, MemoryUsageManyMessages) { + // Mach-based SharedMemory isn't support on OSX 10.6. + if (base::mac::IsOSSnowLeopard()) + return; + + CommonSetUp("MemoryUsageManyMessages"); + + for (int i = 0; i < g_large_message_count; ++i) { + std::string message = base::IntToString(i); + message += '\0'; + size_t end = message.size(); + message.resize(g_medium_message_size); + std::fill(message.begin() + end, message.end(), 'a'); + SendMessage1(message); + + base::MessageLoop::current()->RunUntilIdle(); + } + + if (get_result_listener()->get_result() == RESULT_UNKNOWN) + base::MessageLoop::current()->Run(); + + CommonTearDown(); +} + +void MemoryUsageManyMessagesCallback(IPC::Sender* sender, + const IPC::Message& message, + ChildProcessGlobals* globals) { + static int message_index = 0; + + { + // Map the shared memory, and make sure that its pages are counting towards + // resident size. + base::SharedMemoryHandle shm(GetSharedMemoryHandleFromMsg1(message)); + scoped_ptr<base::SharedMemory> shared_memory( + MapSharedMemoryHandle(shm, false)); + + char* addr = static_cast<char*>(shared_memory->memory()); + std::string message_string(addr); + int message_int; + ASSERT_TRUE(base::StringToInt(message_string, &message_int)); + ASSERT_EQ(message_index, message_int); + for (size_t i = 0; i < g_medium_message_size; i += 1024) { + addr[i] = 'a'; + } + } + + ++message_index; + + if (message_index == 1) { + // Disable message logging, since it significantly contributes towards total + // memory usage. + LOG(INFO) << "Disable privileged process message logging."; + globals->message_logging = false; + } + + if (message_index == g_large_message_count) { + size_t memory_increase_kb = + (GetResidentSize() - globals->initial_resident_size) / 1024; + LOG(INFO) << "Increase in memory usage in KB: " << memory_increase_kb; + +#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ + defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \ + defined(UNDEFINED_SANITIZER) + // Under a sanitizer build, releasing memory does not necessarily reduce the + // amount of resident memory. + bool success = true; +#else + // The total increase in resident size should be less than 1MB. The exact + // amount is not deterministic. + bool success = memory_increase_kb < 1024; +#endif + + SendControlMessage(sender, success); + } +} + +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(MemoryUsageManyMessages) { + return CommonPrivilegedProcessMain(&MemoryUsageManyMessagesCallback, + "MemoryUsageManyMessages"); +} + } // namespace
diff --git a/mandoline/BUILD.gn b/mandoline/BUILD.gn index ff9ff73..f0cac02 100644 --- a/mandoline/BUILD.gn +++ b/mandoline/BUILD.gn
@@ -17,8 +17,8 @@ deps += [ "//mandoline/app/android" ] } else { deps += [ - "//components/mus/example", "//mandoline/app/desktop", + "//mash/example", ] } }
diff --git a/mandoline/ui/desktop_ui/browser_window.cc b/mandoline/ui/desktop_ui/browser_window.cc index 9c6b051..6100a57 100644 --- a/mandoline/ui/desktop_ui/browser_window.cc +++ b/mandoline/ui/desktop_ui/browser_window.cc
@@ -200,6 +200,7 @@ host_->SetSize(mojo::Size::From(gfx::Size(1280, 800))); root_->AddChild(content_); + host_->AddActivationParent(root_->id()); content_->SetVisible(true); web_view_.Init(app_, content_);
diff --git a/mash/BUILD.gn b/mash/BUILD.gn new file mode 100644 index 0000000..32517e2 --- /dev/null +++ b/mash/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("//testing/test.gni") + +# Target that builders build. +group("all") { + testonly = true + + deps = [ + ":mash_unittests", + "//mash/example", + ] +} + +test("mash_unittests") { + deps = [ + "//base", + "//base/test:run_all_unittests", + "//base/test:test_config", + "//base/test:test_support", + "//mash/wm:unittests", + "//mojo/platform_handle:platform_handle_impl", + ] +}
diff --git a/mash/example/BUILD.gn b/mash/example/BUILD.gn new file mode 100644 index 0000000..07198dd --- /dev/null +++ b/mash/example/BUILD.gn
@@ -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. + +import("//testing/test.gni") + +group("example") { + testonly = true + + deps = [ + "//mash/example/main", + "//mash/example/mock_sysui", + "//mash/example/views_examples", + "//mash/example/window_type_launcher", + "//mash/wm", + "//mojo/runner", + ] +}
diff --git a/components/mus/example/DEPS b/mash/example/DEPS similarity index 100% rename from components/mus/example/DEPS rename to mash/example/DEPS
diff --git a/components/mus/example/common/mus_views_init.h b/mash/example/common/mus_views_init.h similarity index 89% rename from components/mus/example/common/mus_views_init.h rename to mash/example/common/mus_views_init.h index d268e9ba..43da4f4 100644 --- a/components/mus/example/common/mus_views_init.h +++ b/mash/example/common/mus_views_init.h
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_MUS_EXAMPLE_COMMON_MUS_VIEWS_INIT_H_ -#define COMPONENTS_MUS_EXAMPLE_COMMON_MUS_VIEWS_INIT_H_ +#ifndef MASH_EXAMPLE_COMMON_MUS_VIEWS_INIT_H_ +#define MASH_EXAMPLE_COMMON_MUS_VIEWS_INIT_H_ +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "components/mus/public/cpp/window_tree_delegate.h" #include "components/mus/public/interfaces/window_manager.mojom.h" @@ -50,4 +51,4 @@ DISALLOW_COPY_AND_ASSIGN(MUSViewsInit); }; -#endif // COMPONENTS_MUS_EXAMPLE_COMMON_MUS_VIEWS_INIT_H_ +#endif // MASH_EXAMPLE_COMMON_MUS_VIEWS_INIT_H_
diff --git a/components/mus/example/main/BUILD.gn b/mash/example/main/BUILD.gn similarity index 86% rename from components/mus/example/main/BUILD.gn rename to mash/example/main/BUILD.gn index abca70e..60c6c3c7 100644 --- a/components/mus/example/main/BUILD.gn +++ b/mash/example/main/BUILD.gn
@@ -25,7 +25,7 @@ ] data_deps = [ - "//components/mus/example/views_examples", - "//components/mus/example/window_type_launcher", + "//mash/example/views_examples", + "//mash/example/window_type_launcher", ] }
diff --git a/components/mus/example/main/main.cc b/mash/example/main/main.cc similarity index 85% rename from components/mus/example/main/main.cc rename to mash/example/main/main.cc index 9815587c..00d5743 100644 --- a/components/mus/example/main/main.cc +++ b/mash/example/main/main.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 "components/mus/example/main/main_application_delegate.h" +#include "mash/example/main/main_application_delegate.h" #include "mojo/application/public/cpp/application_runner.h" #include "mojo/public/c/system/main.h"
diff --git a/components/mus/example/main/main_application_delegate.cc b/mash/example/main/main_application_delegate.cc similarity index 93% rename from components/mus/example/main/main_application_delegate.cc rename to mash/example/main/main_application_delegate.cc index 1e2b08c3..c1d85ba 100644 --- a/components/mus/example/main/main_application_delegate.cc +++ b/mash/example/main/main_application_delegate.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 "components/mus/example/main/main_application_delegate.h" +#include "mash/example/main/main_application_delegate.h" #include "mojo/application/public/cpp/application_connection.h" #include "mojo/application/public/cpp/application_impl.h"
diff --git a/components/mus/example/main/main_application_delegate.h b/mash/example/main/main_application_delegate.h similarity index 80% rename from components/mus/example/main/main_application_delegate.h rename to mash/example/main/main_application_delegate.h index 2c2e6f2..9542d1c 100644 --- a/components/mus/example/main/main_application_delegate.h +++ b/mash/example/main/main_application_delegate.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 COMPONENTS_MUS_EXAMPLE_MAIN_MAIN_APPLICATION_DELEGATE_H_ -#define COMPONENTS_MUS_EXAMPLE_MAIN_MAIN_APPLICATION_DELEGATE_H_ +#ifndef MASH_EXAMPLE_MAIN_MAIN_APPLICATION_DELEGATE_H_ +#define MASH_EXAMPLE_MAIN_MAIN_APPLICATION_DELEGATE_H_ #include "base/macros.h" #include "base/memory/scoped_vector.h" @@ -30,4 +30,4 @@ DISALLOW_COPY_AND_ASSIGN(MainApplicationDelegate); }; -#endif // COMPONENTS_MUS_EXAMPLE_MAIN_MAIN_APPLICATION_DELEGATE_H_ +#endif // MASH_EXAMPLE_MAIN_MAIN_APPLICATION_DELEGATE_H_
diff --git a/components/mus/example/mock_sysui/BUILD.gn b/mash/example/mock_sysui/BUILD.gn similarity index 100% rename from components/mus/example/mock_sysui/BUILD.gn rename to mash/example/mock_sysui/BUILD.gn
diff --git a/components/mus/example/mock_sysui/main.cc b/mash/example/mock_sysui/main.cc similarity index 87% rename from components/mus/example/mock_sysui/main.cc rename to mash/example/mock_sysui/main.cc index d3aba2eb..44d00e93 100644 --- a/components/mus/example/mock_sysui/main.cc +++ b/mash/example/mock_sysui/main.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 "components/mus/example/mock_sysui/mock_sysui.h" +#include "mash/example/mock_sysui/mock_sysui.h" #include "mojo/application/public/cpp/application_runner.h" #include "mojo/public/c/system/main.h"
diff --git a/components/mus/example/mock_sysui/mock_sysui.cc b/mash/example/mock_sysui/mock_sysui.cc similarity index 98% rename from components/mus/example/mock_sysui/mock_sysui.cc rename to mash/example/mock_sysui/mock_sysui.cc index 6a0a67f..57146b88 100644 --- a/components/mus/example/mock_sysui/mock_sysui.cc +++ b/mash/example/mock_sysui/mock_sysui.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 "components/mus/example/mock_sysui/mock_sysui.h" +#include "mash/example/mock_sysui/mock_sysui.h" #include "components/mus/public/cpp/property_type_converters.h" #include "mash/wm/public/interfaces/container.mojom.h"
diff --git a/components/mus/example/mock_sysui/mock_sysui.h b/mash/example/mock_sysui/mock_sysui.h similarity index 82% rename from components/mus/example/mock_sysui/mock_sysui.h rename to mash/example/mock_sysui/mock_sysui.h index b214c641..23e068b 100644 --- a/components/mus/example/mock_sysui/mock_sysui.h +++ b/mash/example/mock_sysui/mock_sysui.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 COMPONENTS_MUS_EXAMPLE_MOCK_SYSUI_MOCK_SYSUI_H_ -#define COMPONENTS_MUS_EXAMPLE_MOCK_SYSUI_MOCK_SYSUI_H_ +#ifndef MASH_EXAMPLE_MOCK_SYSUI_MOCK_SYSUI_H_ +#define MASH_EXAMPLE_MOCK_SYSUI_MOCK_SYSUI_H_ #include "base/macros.h" #include "base/memory/scoped_ptr.h" @@ -32,4 +32,4 @@ DISALLOW_COPY_AND_ASSIGN(MockSysUI); }; -#endif // COMPONENTS_MUS_EXAMPLE_MOCK_SYSUI_MOCK_SYSUI_H_ +#endif // MASH_EXAMPLE_MOCK_SYSUI_MOCK_SYSUI_H_
diff --git a/components/mus/example/views_examples/BUILD.gn b/mash/example/views_examples/BUILD.gn similarity index 100% rename from components/mus/example/views_examples/BUILD.gn rename to mash/example/views_examples/BUILD.gn
diff --git a/components/mus/example/views_examples/main.cc b/mash/example/views_examples/main.cc similarity index 82% rename from components/mus/example/views_examples/main.cc rename to mash/example/views_examples/main.cc index ee1a650..27c727bb 100644 --- a/components/mus/example/views_examples/main.cc +++ b/mash/example/views_examples/main.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 "components/mus/example/views_examples/views_examples_application_delegate.h" +#include "mash/example/views_examples/views_examples_application_delegate.h" #include "mojo/application/public/cpp/application_runner.h" #include "mojo/public/c/system/main.h"
diff --git a/components/mus/example/views_examples/views_examples_application_delegate.cc b/mash/example/views_examples/views_examples_application_delegate.cc similarity index 92% rename from components/mus/example/views_examples/views_examples_application_delegate.cc rename to mash/example/views_examples/views_examples_application_delegate.cc index 176de7f..cf5f46f 100644 --- a/components/mus/example/views_examples/views_examples_application_delegate.cc +++ b/mash/example/views_examples/views_examples_application_delegate.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 "components/mus/example/views_examples/views_examples_application_delegate.h" +#include "mash/example/views_examples/views_examples_application_delegate.h" #include "mojo/application/public/cpp/application_connection.h" #include "mojo/application/public/cpp/application_impl.h"
diff --git a/components/mus/example/views_examples/views_examples_application_delegate.h b/mash/example/views_examples/views_examples_application_delegate.h similarity index 78% rename from components/mus/example/views_examples/views_examples_application_delegate.h rename to mash/example/views_examples/views_examples_application_delegate.h index c317aa2..47fb91a 100644 --- a/components/mus/example/views_examples/views_examples_application_delegate.h +++ b/mash/example/views_examples/views_examples_application_delegate.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 COMPONENTS_MUS_EXAMPLE_CLIENT_VIEWS_EXAMPLES_APPLICATION_DELEGATE_H_ -#define COMPONENTS_MUS_EXAMPLE_CLIENT_VIEWS_EXAMPLES_APPLICATION_DELEGATE_H_ +#ifndef MASH_EXAMPLE_VIEWS_EXAMPLES_APPLICATION_DELEGATE_H_ +#define MASH_EXAMPLE_VIEWS_EXAMPLES_APPLICATION_DELEGATE_H_ #include "base/macros.h" #include "base/memory/scoped_ptr.h" @@ -32,4 +32,4 @@ DISALLOW_COPY_AND_ASSIGN(ViewsExamplesApplicationDelegate); }; -#endif // COMPONENTS_MUS_EXAMPLE_CLIENT_VIEWS_EXAMPLES_APPLICATION_DELEGATE_H_ +#endif // MASH_EXAMPLE_VIEWS_EXAMPLES_APPLICATION_DELEGATE_H_
diff --git a/components/mus/example/window_type_launcher/BUILD.gn b/mash/example/window_type_launcher/BUILD.gn similarity index 100% rename from components/mus/example/window_type_launcher/BUILD.gn rename to mash/example/window_type_launcher/BUILD.gn
diff --git a/components/mus/example/window_type_launcher/DEPS b/mash/example/window_type_launcher/DEPS similarity index 100% rename from components/mus/example/window_type_launcher/DEPS rename to mash/example/window_type_launcher/DEPS
diff --git a/components/mus/example/window_type_launcher/main.cc b/mash/example/window_type_launcher/main.cc similarity index 96% rename from components/mus/example/window_type_launcher/main.cc rename to mash/example/window_type_launcher/main.cc index c2e94f9..56941fc 100644 --- a/components/mus/example/window_type_launcher/main.cc +++ b/mash/example/window_type_launcher/main.cc
@@ -10,7 +10,7 @@ #include "base/process/launch.h" #include "base/threading/thread.h" #include "build/build_config.h" -#include "components/mus/example/window_type_launcher/window_type_launcher.h" +#include "mash/example/window_type_launcher/window_type_launcher.h" #include "mojo/application/public/cpp/application_impl.h" #include "mojo/application/public/interfaces/application.mojom.h" #include "mojo/message_pump/message_pump_mojo.h"
diff --git a/components/mus/example/window_type_launcher/window_type_launcher.cc b/mash/example/window_type_launcher/window_type_launcher.cc similarity index 99% rename from components/mus/example/window_type_launcher/window_type_launcher.cc rename to mash/example/window_type_launcher/window_type_launcher.cc index 67c642c..da05253 100644 --- a/components/mus/example/window_type_launcher/window_type_launcher.cc +++ b/mash/example/window_type_launcher/window_type_launcher.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 "components/mus/example/window_type_launcher/window_type_launcher.h" +#include "mash/example/window_type_launcher/window_type_launcher.h" #include "base/strings/utf_string_conversions.h" #include "mojo/application/public/cpp/application_connection.h"
diff --git a/components/mus/example/window_type_launcher/window_type_launcher.h b/mash/example/window_type_launcher/window_type_launcher.h similarity index 76% rename from components/mus/example/window_type_launcher/window_type_launcher.h rename to mash/example/window_type_launcher/window_type_launcher.h index bdfbd5e..fc072222 100644 --- a/components/mus/example/window_type_launcher/window_type_launcher.h +++ b/mash/example/window_type_launcher/window_type_launcher.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 COMPONENTS_MUS_EXAMPLE_WINDOW_TYPE_LAUNCHER_WINDOW_TYPE_LAUNCHER_H_ -#define COMPONENTS_MUS_EXAMPLE_WINDOW_TYPE_LAUNCHER_WINDOW_TYPE_LAUNCHER_H_ +#ifndef MASH_EXAMPLE_WINDOW_TYPE_LAUNCHER_WINDOW_TYPE_LAUNCHER_H_ +#define MASH_EXAMPLE_WINDOW_TYPE_LAUNCHER_WINDOW_TYPE_LAUNCHER_H_ #include "base/macros.h" #include "base/memory/scoped_ptr.h" @@ -29,4 +29,4 @@ DISALLOW_COPY_AND_ASSIGN(WindowTypeLauncher); }; -#endif // COMPONENTS_MUS_EXAMPLE_WINDOW_TYPE_LAUNCHER_WINDOW_TYPE_LAUNCHER_H_ +#endif // MASH_EXAMPLE_WINDOW_TYPE_LAUNCHER_WINDOW_TYPE_LAUNCHER_H_
diff --git a/mash/wm/resources/default_100_percent/common/window_shadow_active.png b/mash/wm/resources/default_100_percent/common/window_shadow_active.png new file mode 100644 index 0000000..14c4522 --- /dev/null +++ b/mash/wm/resources/default_100_percent/common/window_shadow_active.png Binary files differ
diff --git a/mash/wm/resources/default_100_percent/common/window_shadow_inactive.png b/mash/wm/resources/default_100_percent/common/window_shadow_inactive.png new file mode 100644 index 0000000..2204f7a --- /dev/null +++ b/mash/wm/resources/default_100_percent/common/window_shadow_inactive.png Binary files differ
diff --git a/mash/wm/resources/default_100_percent/common/window_shadow_small.png b/mash/wm/resources/default_100_percent/common/window_shadow_small.png new file mode 100644 index 0000000..9a7b851 --- /dev/null +++ b/mash/wm/resources/default_100_percent/common/window_shadow_small.png Binary files differ
diff --git a/mash/wm/resources/default_200_percent/common/window_shadow_active.png b/mash/wm/resources/default_200_percent/common/window_shadow_active.png new file mode 100644 index 0000000..7ba2a85 --- /dev/null +++ b/mash/wm/resources/default_200_percent/common/window_shadow_active.png Binary files differ
diff --git a/mash/wm/resources/default_200_percent/common/window_shadow_inactive.png b/mash/wm/resources/default_200_percent/common/window_shadow_inactive.png new file mode 100644 index 0000000..c2d3ee8 --- /dev/null +++ b/mash/wm/resources/default_200_percent/common/window_shadow_inactive.png Binary files differ
diff --git a/mash/wm/resources/default_200_percent/common/window_shadow_small.png b/mash/wm/resources/default_200_percent/common/window_shadow_small.png new file mode 100644 index 0000000..8753541 --- /dev/null +++ b/mash/wm/resources/default_200_percent/common/window_shadow_small.png Binary files differ
diff --git a/mash/wm/window_manager_application.cc b/mash/wm/window_manager_application.cc index bf58d79..25a58bf8 100644 --- a/mash/wm/window_manager_application.cc +++ b/mash/wm/window_manager_application.cc
@@ -57,8 +57,12 @@ GetWindowForContainer(mash::wm::mojom::CONTAINER_USER_BACKGROUND))); shelf_layout_.reset(new ShelfLayout( GetWindowForContainer(mash::wm::mojom::CONTAINER_USER_SHELF))); + + mus::Window* window = + GetWindowForContainer(mash::wm::mojom::CONTAINER_USER_WINDOWS); window_layout_.reset(new WindowLayout( GetWindowForContainer(mash::wm::mojom::CONTAINER_USER_WINDOWS))); + host_->AddActivationParent(window->id()); window_manager_.reset(new WindowManagerImpl(this));
diff --git a/mash/wm/window_manager_impl.cc b/mash/wm/window_manager_impl.cc index 46919aa..7078077 100644 --- a/mash/wm/window_manager_impl.cc +++ b/mash/wm/window_manager_impl.cc
@@ -64,16 +64,14 @@ void WindowManagerImpl::OpenWindow( mus::mojom::WindowTreeClientPtr client, - mojo::Map<mojo::String, mojo::Array<uint8_t>> properties) { + mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) { mus::Window* root = state_->root(); DCHECK(root); - mus::Window* child_window = root->connection()->NewWindow(); - // TODO(beng): mus::Window should have a "SetSharedProperties" method that - // joins the supplied map onto the internal one. - for (auto prop : properties) - child_window->SetSharedProperty(prop.GetKey(), prop.GetValue()); - + mus::Window::SharedProperties properties = + transport_properties.To<mus::Window::SharedProperties>(); + // TODO(sky): constrain to valid properties here. + mus::Window* child_window = root->connection()->NewWindow(&properties); child_window->SetBounds(CalculateDefaultBounds(child_window)); GetContainerForChild(child_window)->AddChild(child_window); child_window->Embed(client.Pass());
diff --git a/mash/wm/window_manager_impl.h b/mash/wm/window_manager_impl.h index 40fa8cdee..c03d5af 100644 --- a/mash/wm/window_manager_impl.h +++ b/mash/wm/window_manager_impl.h
@@ -26,9 +26,9 @@ gfx::Rect GetMaximizedWindowBounds() const; // mus::mojom::WindowManager: - void OpenWindow( - mus::mojom::WindowTreeClientPtr client, - mojo::Map<mojo::String, mojo::Array<uint8_t>> properties) override; + void OpenWindow(mus::mojom::WindowTreeClientPtr client, + mojo::Map<mojo::String, mojo::Array<uint8_t>> + transport_properties) override; void GetConfig(const GetConfigCallback& callback) override; mus::Window* GetContainerForChild(mus::Window* child);
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index eb9129a..5a74312 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -214,10 +214,6 @@ "cras/cras_unified.cc", "cras/cras_unified.h", ] - - pkg_config("libcras") { - packages = [ "libcras" ] - } configs += [ ":libcras" ] deps += [ "//chromeos:chromeos" ] } @@ -235,9 +231,6 @@ ] if (link_pulseaudio) { - pkg_config("libpulse") { - packages = [ "libpulse" ] - } configs += [ ":libpulse" ] } else { # TODO(ajwong): Technically, this dl should go in the action. @@ -250,6 +243,18 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] } +if (use_cras) { + pkg_config("libcras") { + packages = [ "libcras" ] + } +} + +if (use_pulseaudio && link_pulseaudio) { + pkg_config("libpulse") { + packages = [ "libpulse" ] + } +} + source_set("test_support") { testonly = true sources = [ @@ -314,7 +319,7 @@ ] } - if (is_chromeos) { + if (is_chromeos || is_chromecast) { sources += [ "sounds/audio_stream_handler_unittest.cc", "sounds/sounds_manager_unittest.cc",
diff --git a/media/audio/mac/audio_low_latency_input_mac.h b/media/audio/mac/audio_low_latency_input_mac.h index 84422fa..982b27b 100644 --- a/media/audio/mac/audio_low_latency_input_mac.h +++ b/media/audio/mac/audio_low_latency_input_mac.h
@@ -164,7 +164,7 @@ // array as soon as a frame of the desired buffer size has been recorded. scoped_ptr<uint8[]> audio_data_buffer_; - // True after successfull Start(), false after successful Stop(). + // True after successful Start(), false after successful Stop(). bool started_; // Fixed capture hardware latency in frames.
diff --git a/media/audio/simple_sources.cc b/media/audio/simple_sources.cc index 877f9fd5..4ded6bd4 100644 --- a/media/audio/simple_sources.cc +++ b/media/audio/simple_sources.cc
@@ -16,13 +16,13 @@ #include "media/base/audio_bus.h" namespace media { - +namespace { // Opens |wav_filename|, reads it and loads it as a wav file. This function will // return a null pointer if we can't read the file or if it's malformed. The // caller takes ownership of the returned data. The size of the data is stored // in |read_length|. -static scoped_ptr<uint8[]> ReadWavFile(const base::FilePath& wav_filename, - size_t* file_length) { +scoped_ptr<char[]> ReadWavFile(const base::FilePath& wav_filename, + size_t* read_length) { base::File wav_file( wav_filename, base::File::FLAG_OPEN | base::File::FLAG_READ); if (!wav_file.IsValid()) { @@ -38,26 +38,14 @@ return nullptr; } - uint8* wav_file_data = new uint8[wav_file_length]; - size_t read_bytes = wav_file.Read(0, reinterpret_cast<char*>(wav_file_data), - wav_file_length); + scoped_ptr<char[]> data(new char[wav_file_length]); + size_t read_bytes = wav_file.Read(0, data.get(), wav_file_length); if (read_bytes != wav_file_length) { LOG(ERROR) << "Failed to read all bytes of " << wav_filename.value(); return nullptr; } - *file_length = wav_file_length; - return scoped_ptr<uint8[]>(wav_file_data); -} - -// Opens |wav_filename|, reads it and loads it as a wav file. This function will -// bluntly trigger CHECKs if we can't read the file or if it's malformed. -static scoped_ptr<WavAudioHandler> CreateWavAudioHandler( - const base::FilePath& wav_filename, const uint8* wav_file_data, - size_t wav_file_length, const AudioParameters& expected_params) { - base::StringPiece wav_data(reinterpret_cast<const char*>(wav_file_data), - wav_file_length); - scoped_ptr<WavAudioHandler> wav_audio_handler(new WavAudioHandler(wav_data)); - return wav_audio_handler.Pass(); + *read_length = wav_file_length; + return data; } // These values are based on experiments for local-to-local @@ -101,6 +89,7 @@ static base::LazyInstance<BeepContext>::Leaky g_beep_context = LAZY_INSTANCE_INITIALIZER; +} // namespace ////////////////////////////////////////////////////////////////////////////// // SineWaveAudioSource implementation. @@ -171,16 +160,24 @@ if (load_failed_) return; - // Read the file, and put its data in a scoped_ptr so it gets deleted later. - size_t file_length = 0; - wav_file_data_ = ReadWavFile(path_to_wav_file, &file_length); - if (!wav_file_data_) { + // Read the file, and put its data in a scoped_ptr so it gets deleted when + // this class destructs. This data must be valid for the lifetime of + // |wav_audio_handler_|. + size_t length = 0u; + raw_wav_data_ = ReadWavFile(path_to_wav_file, &length); + if (!raw_wav_data_) { load_failed_ = true; return; } - wav_audio_handler_ = CreateWavAudioHandler( - path_to_wav_file, wav_file_data_.get(), file_length, params_); + // Attempt to create a handler with this data. If the data is invalid, return. + wav_audio_handler_ = + WavAudioHandler::Create(base::StringPiece(raw_wav_data_.get(), length)); + if (!wav_audio_handler_) { + LOG(ERROR) << "WAV data could be read but is not valid"; + load_failed_ = true; + return; + } // Hook us up so we pull in data from the file into the converter. We need to // modify the wav file's audio parameters since we'll be reading small slices
diff --git a/media/audio/simple_sources.h b/media/audio/simple_sources.h index dcb04fd..7a10a34 100644 --- a/media/audio/simple_sources.h +++ b/media/audio/simple_sources.h
@@ -48,8 +48,8 @@ base::Lock time_lock_; }; -class FileSource : public AudioOutputStream::AudioSourceCallback, - public AudioConverter::InputCallback { +class MEDIA_EXPORT FileSource : public AudioOutputStream::AudioSourceCallback, + public AudioConverter::InputCallback { public: FileSource(const AudioParameters& params, const base::FilePath& path_to_wav_file); @@ -62,7 +62,12 @@ private: AudioParameters params_; base::FilePath path_to_wav_file_; - scoped_ptr<uint8[]> wav_file_data_; + + // The WAV data at |path_to_wav_file_| is read into memory and kept here. + // This memory needs to survive for the lifetime of |wav_audio_handler_|, + // so declare it first. Do not access this member directly. + scoped_ptr<char[]> raw_wav_data_; + scoped_ptr<WavAudioHandler> wav_audio_handler_; scoped_ptr<AudioConverter> file_audio_converter_; int wav_file_read_pos_;
diff --git a/media/audio/simple_sources_unittest.cc b/media/audio/simple_sources_unittest.cc index 51cb740f5..8702af5 100644 --- a/media/audio/simple_sources_unittest.cc +++ b/media/audio/simple_sources_unittest.cc
@@ -4,11 +4,13 @@ #include <limits> +#include "base/files/file_util.h" #include "base/logging.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "media/audio/audio_parameters.h" #include "media/audio/simple_sources.h" +#include "media/audio/sounds/test_data.h" #include "media/base/audio_bus.h" #include "testing/gtest/include/gtest/gtest.h" @@ -75,4 +77,104 @@ EXPECT_EQ(2, source.errors()); } +TEST(SimpleSources, FileSourceTestData) { + const int kNumFrames = 10; + + // Create a temporary file filled with WAV data. + base::FilePath temp_path; + ASSERT_TRUE(base::CreateTemporaryFile(&temp_path)); + base::File temp(temp_path, + base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS); + temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize); + ASSERT_EQ(kTestAudioDataSize, static_cast<size_t>(temp.GetLength())); + temp.Close(); + + // Create AudioParameters which match those in the WAV data. + AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, + CHANNEL_LAYOUT_STEREO, 48000, 16, kNumFrames); + scoped_ptr<AudioBus> audio_bus = AudioBus::Create(2, kNumFrames); + audio_bus->Zero(); + + // Create a FileSource that reads this file. + FileSource source(params, temp_path); + EXPECT_EQ(kNumFrames, source.OnMoreData(audio_bus.get(), 0)); + + // Convert the test data (little-endian) into floats and compare. + const int kFirstSampleIndex = 12 + 8 + 16 + 8; + int16_t data[2]; + data[0] = kTestAudioData[kFirstSampleIndex]; + data[0] |= (kTestAudioData[kFirstSampleIndex + 1] << 8); + data[1] = kTestAudioData[kFirstSampleIndex + 2]; + data[1] |= (kTestAudioData[kFirstSampleIndex + 3] << 8); + + // The first frame should hold the WAV data. + EXPECT_FLOAT_EQ(static_cast<float>(data[0]) / ((1 << 15) - 1), + audio_bus->channel(0)[0]); + EXPECT_FLOAT_EQ(static_cast<float>(data[1]) / ((1 << 15) - 1), + audio_bus->channel(1)[0]); + + // All other frames should be zero-padded. + for (int channel = 0; channel < audio_bus->channels(); ++channel) { + for (int frame = 1; frame < audio_bus->frames(); ++frame) { + EXPECT_FLOAT_EQ(0.0, audio_bus->channel(channel)[frame]); + } + } +} + +TEST(SimpleSources, BadFilePathFails) { + AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, + CHANNEL_LAYOUT_STEREO, 48000, 16, 10); + scoped_ptr<AudioBus> audio_bus = AudioBus::Create(2, 10); + audio_bus->Zero(); + + // Create a FileSource that reads this file. + base::FilePath path; + path = path.Append(FILE_PATH_LITERAL("does")) + .Append(FILE_PATH_LITERAL("not")) + .Append(FILE_PATH_LITERAL("exist")); + FileSource source(params, path); + EXPECT_EQ(0, source.OnMoreData(audio_bus.get(), 0)); + + // Confirm all frames are zero-padded. + for (int channel = 0; channel < audio_bus->channels(); ++channel) { + for (int frame = 0; frame < audio_bus->frames(); ++frame) { + EXPECT_FLOAT_EQ(0.0, audio_bus->channel(channel)[frame]); + } + } +} + +TEST(SimpleSources, FileSourceCorruptTestDataFails) { + const int kNumFrames = 10; + + // Create a temporary file filled with WAV data. + base::FilePath temp_path; + ASSERT_TRUE(base::CreateTemporaryFile(&temp_path)); + base::File temp(temp_path, + base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS); + temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize); + + // Corrupt the header. + temp.Write(3, "0x00", 1); + + ASSERT_EQ(kTestAudioDataSize, static_cast<size_t>(temp.GetLength())); + temp.Close(); + + // Create AudioParameters which match those in the WAV data. + AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, + CHANNEL_LAYOUT_STEREO, 48000, 16, kNumFrames); + scoped_ptr<AudioBus> audio_bus = AudioBus::Create(2, kNumFrames); + audio_bus->Zero(); + + // Create a FileSource that reads this file. + FileSource source(params, temp_path); + EXPECT_EQ(0, source.OnMoreData(audio_bus.get(), 0)); + + // Confirm all frames are zero-padded. + for (int channel = 0; channel < audio_bus->channels(); ++channel) { + for (int frame = 0; frame < audio_bus->frames(); ++frame) { + EXPECT_FLOAT_EQ(0.0, audio_bus->channel(channel)[frame]); + } + } +} + } // namespace media
diff --git a/media/audio/sounds/audio_stream_handler.cc b/media/audio/sounds/audio_stream_handler.cc index 5f175ea..ee27312 100644 --- a/media/audio/sounds/audio_stream_handler.cc +++ b/media/audio/sounds/audio_stream_handler.cc
@@ -13,6 +13,7 @@ #include "base/time/time.h" #include "media/audio/audio_manager.h" #include "media/audio/audio_manager_base.h" +#include "media/audio/sounds/wav_audio_handler.h" #include "media/base/channel_layout.h" namespace media { @@ -36,12 +37,14 @@ class AudioStreamHandler::AudioStreamContainer : public AudioOutputStream::AudioSourceCallback { public: - explicit AudioStreamContainer(const WavAudioHandler& wav_audio) + explicit AudioStreamContainer(scoped_ptr<WavAudioHandler> wav_audio) : started_(false), stream_(NULL), cursor_(0), delayed_stop_posted_(false), - wav_audio_(wav_audio) {} + wav_audio_(wav_audio.Pass()) { + DCHECK(wav_audio_); + } ~AudioStreamContainer() override { DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); @@ -53,8 +56,8 @@ if (!stream_) { const AudioParameters params( AudioParameters::AUDIO_PCM_LOW_LATENCY, - GuessChannelLayout(wav_audio_.num_channels()), - wav_audio_.sample_rate(), wav_audio_.bits_per_sample(), + GuessChannelLayout(wav_audio_->num_channels()), + wav_audio_->sample_rate(), wav_audio_->bits_per_sample(), kDefaultFrameCount); stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params, std::string()); @@ -73,7 +76,7 @@ base::Unretained(this))); if (started_) { - if (wav_audio_.AtEnd(cursor_)) + if (wav_audio_->AtEnd(cursor_)) cursor_ = 0; return; } @@ -107,8 +110,8 @@ base::AutoLock al(state_lock_); size_t bytes_written = 0; - if (wav_audio_.AtEnd(cursor_) || - !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) { + if (wav_audio_->AtEnd(cursor_) || + !wav_audio_->CopyTo(dest, cursor_, &bytes_written)) { if (delayed_stop_posted_) return 0; delayed_stop_posted_ = true; @@ -150,44 +153,53 @@ base::Lock state_lock_; size_t cursor_; bool delayed_stop_posted_; - const WavAudioHandler wav_audio_; + scoped_ptr<WavAudioHandler> wav_audio_; base::CancelableClosure stop_closure_; DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer); }; -AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) - : wav_audio_(wav_data), - initialized_(false) { +AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) { AudioManager* manager = AudioManager::Get(); if (!manager) { LOG(ERROR) << "Can't get access to audio manager."; return; } + + scoped_ptr<WavAudioHandler> wav_audio = WavAudioHandler::Create(wav_data); + if (!wav_audio) { + LOG(ERROR) << "wav_data is not valid"; + return; + } + const AudioParameters params( AudioParameters::AUDIO_PCM_LOW_LATENCY, - GuessChannelLayout(wav_audio_.num_channels()), wav_audio_.sample_rate(), - wav_audio_.bits_per_sample(), kDefaultFrameCount); + GuessChannelLayout(wav_audio->num_channels()), wav_audio->sample_rate(), + wav_audio->bits_per_sample(), kDefaultFrameCount); if (!params.IsValid()) { LOG(ERROR) << "Audio params are invalid."; return; } - stream_.reset(new AudioStreamContainer(wav_audio_)); - initialized_ = true; + + // Store the duration of the WAV data then pass the handler to |stream_|. + duration_ = wav_audio->GetDuration(); + stream_.reset(new AudioStreamContainer(wav_audio.Pass())); } AudioStreamHandler::~AudioStreamHandler() { DCHECK(CalledOnValidThread()); - AudioManager::Get()->GetTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); - AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, - stream_.release()); + if (IsInitialized()) { + AudioManager::Get()->GetTaskRunner()->PostTask( + FROM_HERE, base::Bind(&AudioStreamContainer::Stop, + base::Unretained(stream_.get()))); + AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, + stream_.release()); + } } bool AudioStreamHandler::IsInitialized() const { DCHECK(CalledOnValidThread()); - return initialized_; + return stream_; } bool AudioStreamHandler::Play() { @@ -205,11 +217,20 @@ void AudioStreamHandler::Stop() { DCHECK(CalledOnValidThread()); + + if (!IsInitialized()) + return; + AudioManager::Get()->GetTaskRunner()->PostTask( FROM_HERE, base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); } +base::TimeDelta AudioStreamHandler::duration() const { + DCHECK(CalledOnValidThread()); + return duration_; +} + // static void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) { g_observer_for_testing = observer;
diff --git a/media/audio/sounds/audio_stream_handler.h b/media/audio/sounds/audio_stream_handler.h index f814aae..4caa603 100644 --- a/media/audio/sounds/audio_stream_handler.h +++ b/media/audio/sounds/audio_stream_handler.h
@@ -9,9 +9,9 @@ #include "base/compiler_specific.h" #include "base/strings/string_piece.h" #include "base/threading/non_thread_safe.h" +#include "base/time/time.h" #include "media/audio/audio_io.h" #include "media/audio/audio_parameters.h" -#include "media/audio/sounds/wav_audio_handler.h" #include "media/base/media_export.h" namespace media { @@ -53,7 +53,8 @@ // Stops current playback. void Stop(); - const WavAudioHandler& wav_audio_handler() const { return wav_audio_; } + // Get the duration of the WAV data passed in. + base::TimeDelta duration() const; private: friend class AudioStreamHandlerTest; @@ -65,11 +66,9 @@ static void SetAudioSourceForTesting( AudioOutputStream::AudioSourceCallback* source); - WavAudioHandler wav_audio_; + base::TimeDelta duration_; scoped_ptr<AudioStreamContainer> stream_; - bool initialized_; - DISALLOW_COPY_AND_ASSIGN(AudioStreamHandler); };
diff --git a/media/audio/sounds/audio_stream_handler_unittest.cc b/media/audio/sounds/audio_stream_handler_unittest.cc index 234ac9d..5393162 100644 --- a/media/audio/sounds/audio_stream_handler_unittest.cc +++ b/media/audio/sounds/audio_stream_handler_unittest.cc
@@ -63,6 +63,9 @@ SetObserverForTesting(&observer); ASSERT_TRUE(audio_stream_handler()->IsInitialized()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(20u), + audio_stream_handler()->duration()); + ASSERT_TRUE(audio_stream_handler()->Play()); run_loop.Run(); @@ -83,6 +86,8 @@ SetAudioSourceForTesting(&source); ASSERT_TRUE(audio_stream_handler()->IsInitialized()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(20u), + audio_stream_handler()->duration()); ASSERT_TRUE(audio_stream_handler()->Play()); base::MessageLoop::current()->PostDelayedTask( @@ -105,4 +110,16 @@ ASSERT_EQ(1, observer.num_stop_requests()); } +TEST_F(AudioStreamHandlerTest, BadWavDataDoesNotInitialize) { + // The class members and SetUp() will be ignored for this test. Create a + // handler on the stack with some bad WAV data. + AudioStreamHandler handler("RIFF1234WAVEjunkjunkjunkjunk"); + EXPECT_FALSE(handler.IsInitialized()); + EXPECT_FALSE(handler.Play()); + EXPECT_EQ(base::TimeDelta(), handler.duration()); + + // Call Stop() to ensure that there is no crash. + handler.Stop(); +} + } // namespace media
diff --git a/media/audio/sounds/sounds_manager.cc b/media/audio/sounds/sounds_manager.cc index 17f0dd87..9774ce8 100644 --- a/media/audio/sounds/sounds_manager.cc +++ b/media/audio/sounds/sounds_manager.cc
@@ -64,19 +64,13 @@ bool SoundsManagerImpl::Play(SoundKey key) { DCHECK(CalledOnValidThread()); linked_ptr<AudioStreamHandler> handler = GetHandler(key); - if (!handler.get()) - return false; - if (!handler->IsInitialized()) - return false; - return handler->Play(); + return handler.get() && handler->IsInitialized() && handler->Play(); } bool SoundsManagerImpl::Stop(SoundKey key) { DCHECK(CalledOnValidThread()); linked_ptr<AudioStreamHandler> handler = GetHandler(key); - if (!handler.get()) - return false; - if (!handler->IsInitialized()) + if (!handler.get() || !handler->IsInitialized()) return false; handler->Stop(); return true; @@ -85,12 +79,9 @@ base::TimeDelta SoundsManagerImpl::GetDuration(SoundKey key) { DCHECK(CalledOnValidThread()); linked_ptr<AudioStreamHandler> handler = GetHandler(key); - if (!handler.get()) + if (!handler.get() || !handler->IsInitialized()) return base::TimeDelta(); - if (!handler->IsInitialized()) - return base::TimeDelta(); - const WavAudioHandler& wav_audio = handler->wav_audio_handler(); - return wav_audio.GetDuration(); + return handler->duration(); } linked_ptr<AudioStreamHandler> SoundsManagerImpl::GetHandler(SoundKey key) {
diff --git a/media/audio/sounds/test_data.h b/media/audio/sounds/test_data.h index e5544d0..ce81266 100644 --- a/media/audio/sounds/test_data.h +++ b/media/audio/sounds/test_data.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 MEDIA_AUDIO_SOUNDS_TEST_UTILS_H_ -#define MEDIA_AUDIO_SOUNDS_TEST_UTILS_H_ +#ifndef MEDIA_AUDIO_SOUNDS_TEST_DATA_H_ +#define MEDIA_AUDIO_SOUNDS_TEST_DATA_H_ #include "base/basictypes.h" #include "base/callback.h" @@ -18,9 +18,11 @@ const int kTestAudioKey = 1000; -const char kTestAudioData[] = "RIFF\x26\x00\x00\x00WAVEfmt \x10\x00\x00\x00" +const char kTestAudioData[] = + "RIFF\x28\x00\x00\x00WAVEfmt \x10\x00\x00\x00" "\x01\x00\x02\x00\x80\xbb\x00\x00\x00\x77\x01\x00\x02\x00\x10\x00" "data\x04\x00\x00\x00\x01\x00\x01\x00"; +const size_t kTestAudioDataSize = arraysize(kTestAudioData) - 1; class TestObserver : public AudioStreamHandler::TestObserver { public: @@ -48,4 +50,4 @@ } // namespace media -#endif // MEDIA_AUDIO_SOUNDS_TEST_UTILS_H_ +#endif // MEDIA_AUDIO_SOUNDS_TEST_DATA_H_
diff --git a/media/audio/sounds/wav_audio_handler.cc b/media/audio/sounds/wav_audio_handler.cc index c980839..9e271976 100644 --- a/media/audio/sounds/wav_audio_handler.cc +++ b/media/audio/sounds/wav_audio_handler.cc
@@ -11,12 +11,13 @@ #include "base/sys_byteorder.h" #include "media/base/audio_bus.h" +namespace media { namespace { const char kChunkId[] = "RIFF"; const char kFormat[] = "WAVE"; -const char kSubchunk1Id[] = "fmt "; -const char kSubchunk2Id[] = "data"; +const char kFmtSubchunkId[] = "fmt "; +const char kDataSubchunkId[] = "data"; // The size of the header of a wav file. The header consists of 'RIFF', 4 bytes // of total data length, and 'WAVE'. @@ -38,6 +39,20 @@ // Some constants for audio format. const int kAudioFormatPCM = 1; +// A convenience struct for passing WAV parameters around. AudioParameters is +// too heavyweight for this. Keep this class internal to this implementation. +struct WavAudioParameters { + int audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint16_t bits_per_sample; +}; + +bool ParamsAreValid(const WavAudioParameters& params) { + return (params.audio_format == kAudioFormatPCM && params.num_channels != 0u && + params.sample_rate != 0u && params.bits_per_sample != 0u); +} + // Reads an integer from |data| with |offset|. template <typename T> T ReadInt(const base::StringPiece& data, size_t offset) { @@ -50,31 +65,128 @@ return result; } -} // namespace +// Parse a "fmt " chunk from wav data into its parameters. +bool ParseFmtChunk(const base::StringPiece data, WavAudioParameters* params) { + DCHECK(params); -namespace media { - -WavAudioHandler::WavAudioHandler(const base::StringPiece& wav_data) - : num_channels_(0), sample_rate_(0), bits_per_sample_(0), total_frames_(0) { - CHECK_LE(kWavFileHeaderSize, wav_data.size()) << "wav data is too small"; - CHECK(wav_data.starts_with(kChunkId) && - memcmp(wav_data.data() + 8, kFormat, 4) == 0) - << "incorrect wav header"; - - uint32 total_length = std::min(ReadInt<uint32>(wav_data, 4), - static_cast<uint32>(wav_data.size())); - uint32 offset = kWavFileHeaderSize; - while (offset < total_length) { - const int length = ParseSubChunk(wav_data.substr(offset)); - CHECK_LE(0, length) << "can't parse wav sub-chunk"; - offset += length; + // If the chunk is too small, return false. + if (data.size() < kFmtChunkMinimumSize) { + LOG(ERROR) << "Data size " << data.size() << " is too short."; + return false; } + // Read in serialized parameters. + params->audio_format = ReadInt<uint16>(data, kAudioFormatOffset); + params->num_channels = ReadInt<uint16>(data, kChannelOffset); + params->sample_rate = ReadInt<uint32>(data, kSampleRateOffset); + params->bits_per_sample = ReadInt<uint16>(data, kBitsPerSampleOffset); + return true; +} + +bool ParseWavData(const base::StringPiece wav_data, + base::StringPiece* audio_data_out, + WavAudioParameters* params_out) { + DCHECK(audio_data_out); + DCHECK(params_out); + + // The data is not long enough to contain a header. + if (wav_data.size() < kWavFileHeaderSize) { + LOG(ERROR) << "wav_data is too small"; + return false; + } + + // The header should look like: |R|I|F|F|1|2|3|4|W|A|V|E| + if (!wav_data.starts_with(kChunkId) || + memcmp(wav_data.data() + 8, kFormat, 4) != 0) { + LOG(ERROR) << "incorrect wav header"; + return false; + } + + // Get the total length of the data. This number should reflect the total + // number of valid bytes in |wav_data|. Read this from the header and add + // 8 (4 for "RIFF" and 4 for the size itself), and if that is too big, use + // the length of |wav_data|. We will attempt to parse the data. + uint32_t total_length = std::min(ReadInt<uint32_t>(wav_data, 4) + 8, + static_cast<uint32_t>(wav_data.size())); + + uint32_t offset = kWavFileHeaderSize; + bool got_format = false; + while (offset < total_length) { + // This is just junk left at the end. Break. + if (total_length - offset < kChunkHeaderSize) + break; + + // We should be at the beginning of a subsection. The next 8 bytes are the + // header and should look like: "|f|m|t| |1|2|3|4|" or "|d|a|t|a|1|2|3|4|". + // Get the |chunk_header| and the |chunk_payload that follows. + base::StringPiece chunk_header = wav_data.substr(offset, kChunkHeaderSize); + uint32_t chunk_length = ReadInt<uint32_t>(chunk_header, 4); + base::StringPiece chunk_payload = + wav_data.substr(offset + kChunkHeaderSize, chunk_length); + + // Parse the subsection header, handling it if it is a "data" or "fmt " + // chunk. Skip it otherwise. + if (chunk_header.starts_with(kFmtSubchunkId)) { + got_format = true; + if (!ParseFmtChunk(chunk_payload, params_out)) + return false; + } else if (chunk_header.starts_with(kDataSubchunkId)) { + *audio_data_out = chunk_payload; + } else { + DVLOG(1) << "Skipping unknown data chunk: " << chunk_header.substr(0, 4) + << "."; + } + + offset += kChunkHeaderSize + chunk_length; + } + + // Check that data format has been read in and is valid. + if (!got_format) { + LOG(ERROR) << "Invalid: No \"" << kFmtSubchunkId << "\" header found!"; + return false; + } else if (!ParamsAreValid(*params_out)) { + LOG(ERROR) << "Format is invalid. " + << "num_channels: " << params_out->num_channels << " " + << "sample_rate: " << params_out->sample_rate << " " + << "bits_per_sample: " << params_out->bits_per_sample; + return false; + } + return true; +} + +} // namespace + +WavAudioHandler::WavAudioHandler(base::StringPiece audio_data, + uint16_t num_channels, + uint32_t sample_rate, + uint16_t bits_per_sample) + : data_(audio_data), + num_channels_(num_channels), + sample_rate_(sample_rate), + bits_per_sample_(bits_per_sample) { + DCHECK_NE(num_channels_, 0u); + DCHECK_NE(sample_rate_, 0u); + DCHECK_NE(bits_per_sample_, 0u); total_frames_ = data_.size() * 8 / num_channels_ / bits_per_sample_; } WavAudioHandler::~WavAudioHandler() {} +// static +scoped_ptr<WavAudioHandler> WavAudioHandler::Create( + const base::StringPiece wav_data) { + WavAudioParameters params; + base::StringPiece audio_data; + + // Attempt to parse the WAV data. + if (!ParseWavData(wav_data, &audio_data, ¶ms)) + return scoped_ptr<WavAudioHandler>(); + + return make_scoped_ptr(new WavAudioHandler(audio_data, params.num_channels, + params.sample_rate, + params.bits_per_sample)); +} + bool WavAudioHandler::AtEnd(size_t cursor) const { return data_.size() <= cursor; } @@ -107,37 +219,4 @@ static_cast<double>(sample_rate_)); } -int WavAudioHandler::ParseSubChunk(const base::StringPiece& data) { - if (data.size() < kChunkHeaderSize) - return data.size(); - uint32 chunk_length = ReadInt<uint32>(data, 4); - if (data.starts_with(kSubchunk1Id)) { - if (!ParseFmtChunk(data.substr(kChunkHeaderSize, chunk_length))) - return -1; - } else if (data.starts_with(kSubchunk2Id)) { - if (!ParseDataChunk(data.substr(kChunkHeaderSize, chunk_length))) - return -1; - } else { - DVLOG(1) << "Unknown data chunk: " << data.substr(0, 4) << "."; - } - return chunk_length + kChunkHeaderSize; -} - -bool WavAudioHandler::ParseFmtChunk(const base::StringPiece& data) { - if (data.size() < kFmtChunkMinimumSize) { - DLOG(ERROR) << "Data size " << data.size() << " is too short."; - return false; - } - DCHECK_EQ(ReadInt<uint16>(data, kAudioFormatOffset), kAudioFormatPCM); - num_channels_ = ReadInt<uint16>(data, kChannelOffset); - sample_rate_ = ReadInt<uint32>(data, kSampleRateOffset); - bits_per_sample_ = ReadInt<uint16>(data, kBitsPerSampleOffset); - return true; -} - -bool WavAudioHandler::ParseDataChunk(const base::StringPiece& data) { - data_ = data; - return true; -} - } // namespace media
diff --git a/media/audio/sounds/wav_audio_handler.h b/media/audio/sounds/wav_audio_handler.h index 6e404fa..1ea19726 100644 --- a/media/audio/sounds/wav_audio_handler.h +++ b/media/audio/sounds/wav_audio_handler.h
@@ -5,6 +5,8 @@ #ifndef MEDIA_AUDIO_SOUNDS_WAV_AUDIO_HANDLER_H_ #define MEDIA_AUDIO_SOUNDS_WAV_AUDIO_HANDLER_H_ +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/string_piece.h" #include "base/time/time.h" #include "media/base/media_export.h" @@ -17,15 +19,20 @@ // https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ class MEDIA_EXPORT WavAudioHandler { public: - explicit WavAudioHandler(const base::StringPiece& wav_data); virtual ~WavAudioHandler(); + // Create a WavAudioHandler using |wav_data|. If |wav_data| cannot be parsed + // correctly, the returned scoped_ptr will be null. The underlying memory for + // wav_data must survive for the lifetime of this class. + static scoped_ptr<WavAudioHandler> Create(const base::StringPiece wav_data); + // Returns true when cursor points to the end of the track. bool AtEnd(size_t cursor) const; // Copies the audio data to |bus| starting from the |cursor| and in // the case of success stores the number of written bytes in - // |bytes_written|. |bytes_written| should not be NULL. + // |bytes_written|. |bytes_written| should not be NULL. Returns false if the + // operation was unsuccessful. Returns true otherwise. bool CopyTo(AudioBus* bus, size_t cursor, size_t* bytes_written) const; // Accessors. @@ -39,22 +46,20 @@ base::TimeDelta GetDuration() const; private: - // Parses a chunk of wav format data. Returns the length of the chunk. - int ParseSubChunk(const base::StringPiece& data); - - // Parses the 'fmt' section chunk and stores |params_|. - bool ParseFmtChunk(const base::StringPiece& data); - - // Parses the 'data' section chunk and stores |data_|. - bool ParseDataChunk(const base::StringPiece& data); + // Note: It is preferred to pass |audio_data| by value here. + WavAudioHandler(base::StringPiece audio_data, + uint16_t num_channels, + uint32_t sample_rate, + uint16_t bits_per_sample); // Data part of the |wav_data_|. - base::StringPiece data_; - - uint16_t num_channels_; - uint32_t sample_rate_; - uint16_t bits_per_sample_; + const base::StringPiece data_; + const uint16_t num_channels_; + const uint32_t sample_rate_; + const uint16_t bits_per_sample_; uint32_t total_frames_; + + DISALLOW_COPY_AND_ASSIGN(WavAudioHandler); }; } // namespace media
diff --git a/media/audio/sounds/wav_audio_handler_unittest.cc b/media/audio/sounds/wav_audio_handler_unittest.cc index d4ec83a5..5f8c6be 100644 --- a/media/audio/sounds/wav_audio_handler_unittest.cc +++ b/media/audio/sounds/wav_audio_handler_unittest.cc
@@ -12,26 +12,179 @@ #include "testing/gtest/include/gtest/gtest.h" namespace media { +namespace { +// WAV header comes first in the test data. +const size_t kWavHeaderSize = 12; +const size_t kWavDataSizeIndex = 4; + +// "fmt " header comes next. +const size_t kFormatHeaderIndex = kWavHeaderSize; +const size_t kFormatHeaderSize = 8; +const size_t kFormatPayloadSize = 16; +const size_t kChannelIndex = kWavHeaderSize + kFormatHeaderSize + 2; +const size_t kBitsPerSampleIndex = kWavHeaderSize + kFormatHeaderSize + 14; +const size_t kSampleRateIndex = kWavHeaderSize + kFormatHeaderSize + 4; + +// "data" header comes last. +const size_t kDataHeaderIndex = + kWavHeaderSize + kFormatHeaderSize + kFormatPayloadSize; + +} // namespace TEST(WavAudioHandlerTest, SampleDataTest) { - WavAudioHandler handler(base::StringPiece(kTestAudioData, - arraysize(kTestAudioData))); - ASSERT_EQ(2u, handler.num_channels()); - ASSERT_EQ(16u, handler.bits_per_sample()); - ASSERT_EQ(48000u, handler.sample_rate()); - ASSERT_EQ(1u, handler.total_frames()); - ASSERT_EQ(20u, handler.GetDuration().InMicroseconds()); + std::string data(kTestAudioData, kTestAudioDataSize); + auto handler = WavAudioHandler::Create(data); + ASSERT_TRUE(handler); + ASSERT_EQ(2u, handler->num_channels()); + ASSERT_EQ(16u, handler->bits_per_sample()); + ASSERT_EQ(48000u, handler->sample_rate()); + ASSERT_EQ(1u, handler->total_frames()); + ASSERT_EQ(20u, handler->GetDuration().InMicroseconds()); - ASSERT_EQ(4U, handler.data().size()); + ASSERT_EQ(4U, handler->data().size()); const char kData[] = "\x01\x00\x01\x00"; - ASSERT_EQ(base::StringPiece(kData, arraysize(kData) - 1), handler.data()); + ASSERT_EQ(base::StringPiece(kData, arraysize(kData) - 1), handler->data()); - scoped_ptr<AudioBus> bus = AudioBus::Create( - handler.num_channels(), handler.data().size() / handler.num_channels()); + scoped_ptr<AudioBus> bus = + AudioBus::Create(handler->num_channels(), + handler->data().size() / handler->num_channels()); - size_t bytes_written; - ASSERT_TRUE(handler.CopyTo(bus.get(), 0, &bytes_written)); - ASSERT_EQ(static_cast<size_t>(handler.data().size()), bytes_written); + size_t bytes_written = 0u; + ASSERT_TRUE(handler->CopyTo(bus.get(), 0, &bytes_written)); + ASSERT_EQ(static_cast<size_t>(handler->data().size()), bytes_written); +} + +TEST(WavAudioHandlerTest, TestZeroChannelsIsNotValid) { + // Read in the sample data and modify the channel field to hold |00|00|. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kChannelIndex] = '\x00'; + data[kChannelIndex + 1] = '\x00'; + auto handler = WavAudioHandler::Create(data); + EXPECT_FALSE(handler); +} + +TEST(WavAudioHandlerTest, TestZeroBitsPerSampleIsNotValid) { + // Read in the sample data and modify the bits_per_sample field to hold + // |00|00|. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kBitsPerSampleIndex] = '\x00'; + data[kBitsPerSampleIndex + 1] = '\x00'; + auto handler = WavAudioHandler::Create(data); + EXPECT_FALSE(handler); +} + +TEST(WavAudioHandlerTest, TestZeroSamplesPerSecondIsNotValid) { + // Read in the sample data and modify the bits_per_sample field to hold + // |00|00|. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kSampleRateIndex] = '\x00'; + data[kSampleRateIndex + 1] = '\x00'; + data[kSampleRateIndex + 2] = '\x00'; + data[kSampleRateIndex + 3] = '\x00'; + auto handler = WavAudioHandler::Create(data); + EXPECT_FALSE(handler); +} + +TEST(WavAudioHandlerTest, TestTooBigTotalSizeIsOkay) { + // The size filed in the header should hold a very big number. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kWavDataSizeIndex] = '\x00'; + data[kWavDataSizeIndex + 1] = '\xFF'; + data[kWavDataSizeIndex + 2] = '\xFF'; + data[kWavDataSizeIndex + 3] = '\x00'; + auto handler = WavAudioHandler::Create(data); + EXPECT_TRUE(handler); + ASSERT_EQ(2u, handler->num_channels()); + ASSERT_EQ(16u, handler->bits_per_sample()); + ASSERT_EQ(48000u, handler->sample_rate()); + ASSERT_EQ(1u, handler->total_frames()); + ASSERT_EQ(20u, handler->GetDuration().InMicroseconds()); + + ASSERT_EQ(4U, handler->data().size()); + const char kData[] = "\x01\x00\x01\x00"; + ASSERT_EQ(base::StringPiece(kData, arraysize(kData) - 1), handler->data()); +} + +TEST(WavAudioHandlerTest, TestTooBigDataChunkSizeIsOkay) { + // If the |data| chunk size is last and it indicates it has more than it + // actually does, that's okay. Just consume the rest of the string. If it + // is not the last subsection, this file will parse badly. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kDataHeaderIndex + 4] = '\x00'; + data[kDataHeaderIndex + 5] = '\xFF'; + data[kDataHeaderIndex + 6] = '\xFF'; + data[kDataHeaderIndex + 7] = '\x00'; + auto handler = WavAudioHandler::Create(data); + EXPECT_TRUE(handler); + ASSERT_EQ(2u, handler->num_channels()); + ASSERT_EQ(16u, handler->bits_per_sample()); + ASSERT_EQ(48000u, handler->sample_rate()); + ASSERT_EQ(1u, handler->total_frames()); + ASSERT_EQ(20u, handler->GetDuration().InMicroseconds()); + + ASSERT_EQ(4U, handler->data().size()); + const char kData[] = "\x01\x00\x01\x00"; + ASSERT_EQ(base::StringPiece(kData, arraysize(kData) - 1), handler->data()); +} + +TEST(WavAudioHandlerTest, TestTooSmallFormatSizeIsNotValid) { + // If the |data| chunk size is last and it indicates it has more than it + // actually does, that's okay. Just consume the rest of the string. If it + // is not the last subsection, this file will parse badly. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kFormatHeaderIndex + 4] = '\x04'; + data[kFormatHeaderIndex + 5] = '\x00'; + data[kFormatHeaderIndex + 6] = '\x00'; + data[kFormatHeaderIndex + 7] = '\x00'; + auto handler = WavAudioHandler::Create(data); + EXPECT_FALSE(handler); +} + +TEST(WavAudioHandlerTest, TestOtherSectionTypesIsOkay) { + // Append some other subsection header "abcd", the class should just consume + // and keep going. + std::string data(kTestAudioData, kTestAudioDataSize); + data.append("abcd\x04\x00\x00\x00\x01\x02\x03\x04"); + data[kWavDataSizeIndex] += 12; // This should not overflow. + + auto handler = WavAudioHandler::Create(data); + EXPECT_TRUE(handler); + ASSERT_EQ(2u, handler->num_channels()); + ASSERT_EQ(16u, handler->bits_per_sample()); + ASSERT_EQ(48000u, handler->sample_rate()); + ASSERT_EQ(1u, handler->total_frames()); + ASSERT_EQ(20u, handler->GetDuration().InMicroseconds()); + ASSERT_EQ(4u, handler->data().size()); +} + +TEST(WavAudioHandlerTest, TestNoFmtSectionIsNotValid) { + // Write over the "fmt " header. No valid handler should be returned. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kFormatHeaderIndex] = 'a'; + data[kFormatHeaderIndex + 1] = 'b'; + data[kFormatHeaderIndex + 2] = 'c'; + data[kFormatHeaderIndex + 3] = 'd'; + auto handler = WavAudioHandler::Create(data); + EXPECT_FALSE(handler); +} + +TEST(WavAudioHandlerTest, TestNoDataSectionIsOkay) { + // This one could go both ways. But for now, let's say that it's okay not + // to have a "data" section - just make sure everything is zeroed out as it + // should be. + std::string data(kTestAudioData, kTestAudioDataSize); + data[kDataHeaderIndex] = 'a'; + data[kDataHeaderIndex + 1] = 'b'; + data[kDataHeaderIndex + 2] = 'c'; + data[kDataHeaderIndex + 3] = 'd'; + auto handler = WavAudioHandler::Create(data); + EXPECT_TRUE(handler); + ASSERT_EQ(2u, handler->num_channels()); + ASSERT_EQ(16u, handler->bits_per_sample()); + ASSERT_EQ(48000u, handler->sample_rate()); + ASSERT_EQ(0u, handler->total_frames()); + ASSERT_EQ(0u, handler->GetDuration().InMicroseconds()); + ASSERT_EQ(0u, handler->data().size()); } } // namespace media
diff --git a/media/capture/video/mac/platform_video_capturing_mac.h b/media/capture/video/mac/platform_video_capturing_mac.h index 13cc6a2c..7898b97 100644 --- a/media/capture/video/mac/platform_video_capturing_mac.h +++ b/media/capture/video/mac/platform_video_capturing_mac.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 MEDIA_VIDEO_CAPTURE_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ +#ifndef MEDIA_CAPTURE_VIDEO_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ +#define MEDIA_CAPTURE_VIDEO_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ #import <Foundation/Foundation.h> @@ -32,7 +32,7 @@ // device names are usually obtained via VideoCaptureDevice::GetDeviceNames() // method. This method will also configure all device properties except those in // setCaptureHeight:width:frameRate. If |deviceId| is nil, capture is stopped -// and all potential configuration is torn down. Returns YES on sucess, NO +// and all potential configuration is torn down. Returns YES on success, NO // otherwise. - (BOOL)setCaptureDevice:(NSString*)deviceId; @@ -41,7 +41,7 @@ width:(int)width frameRate:(float)frameRate; -// Starts video capturing, registers observers. Returns YES on sucess, NO +// Starts video capturing, registers observers. Returns YES on success, NO // otherwise. - (BOOL)startCapture; @@ -50,4 +50,4 @@ @end -#endif // MEDIA_VIDEO_CAPTURE_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ +#endif // MEDIA_CAPTURE_VIDEO_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.h b/media/capture/video/mac/video_capture_device_avfoundation_mac.h index 539dffc..f4d161d 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.h +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.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 MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ +#ifndef MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ +#define MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ #import <Foundation/Foundation.h> @@ -98,7 +98,7 @@ // the deviceId is known, the library objects are created if needed and // connected for the capture, and a by default resolution is set. If deviceId is // nil, then the eventual capture is stopped and library objects are -// disconnected. Returns YES on sucess, NO otherwise. This method should not be +// disconnected. Returns YES on success, NO otherwise. This method should not be // called during capture. - (BOOL)setCaptureDevice:(NSString*)deviceId; @@ -111,7 +111,7 @@ // Starts video capturing and register the notification listeners. Must be // called after setCaptureDevice:, and, eventually, also after -// setCaptureHeight:width:frameRate:. Returns YES on sucess, NO otherwise. +// setCaptureHeight:width:frameRate:. Returns YES on success, NO otherwise. - (BOOL)startCapture; // Stops video capturing and stops listening to notifications. @@ -119,4 +119,4 @@ @end -#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ +#endif // MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
diff --git a/media/capture/video/mac/video_capture_device_qtkit_mac.h b/media/capture/video/mac/video_capture_device_qtkit_mac.h index a96dd6cf..e4248b2 100644 --- a/media/capture/video/mac/video_capture_device_qtkit_mac.h +++ b/media/capture/video/mac/video_capture_device_qtkit_mac.h
@@ -5,8 +5,8 @@ // VideoCaptureDeviceQTKit implements all QTKit related code for // communicating with a QTKit capture device. -#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ +#ifndef MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ +#define MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ #import <Foundation/Foundation.h> @@ -54,7 +54,7 @@ // Set the frame receiver. - (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver; -// Sets which capture device to use. Returns YES on sucess, NO otherwise. +// Sets which capture device to use. Returns YES on success, NO otherwise. - (BOOL)setCaptureDevice:(NSString*)deviceId; // Configures the capture properties. @@ -62,7 +62,7 @@ width:(int)width frameRate:(float)frameRate; -// Start video capturing. Returns YES on sucess, NO otherwise. +// Start video capturing. Returns YES on success, NO otherwise. - (BOOL)startCapture; // Stops video capturing. @@ -73,4 +73,4 @@ @end -#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ +#endif // MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc index 4b4c930..5655a0f0 100644 --- a/media/cast/sender/video_sender_unittest.cc +++ b/media/cast/sender/video_sender_unittest.cc
@@ -183,7 +183,7 @@ } // If |external| is true then external video encoder (VEA) is used. - // |expect_init_sucess| is true if initialization is expected to succeed. + // |expect_init_success| is true if initialization is expected to succeed. void InitEncoder(bool external, bool expect_init_success) { VideoSenderConfig video_config = GetDefaultVideoSenderConfig(); video_config.use_external_encoder = external; @@ -253,6 +253,7 @@ int last_pixel_value_; base::TimeTicks first_frame_timestamp_; + private: DISALLOW_COPY_AND_ASSIGN(VideoSenderTest); };
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc index 180c002a..d9721b0 100644 --- a/media/filters/vpx_video_decoder.cc +++ b/media/filters/vpx_video_decoder.cc
@@ -118,8 +118,8 @@ // being used by libvpx. Parameters: // |user_priv| Private data passed to libvpx (pointer to memory pool). // |fb| Pointer to the frame buffer that's being released. - static int32 ReleaseVP9FrameBuffer(void *user_priv, - vpx_codec_frame_buffer *fb); + static int32 ReleaseVP9FrameBuffer(void* user_priv, + vpx_codec_frame_buffer* fb); // Generates a "no_longer_needed" closure that holds a reference to this pool. base::Closure CreateFrameCallback(void* fb_priv_data); @@ -216,7 +216,8 @@ } int32 VpxVideoDecoder::MemoryPool::ReleaseVP9FrameBuffer( - void *user_priv, vpx_codec_frame_buffer *fb) { + void* user_priv, + vpx_codec_frame_buffer* fb) { DCHECK(user_priv); DCHECK(fb); VP9FrameBuffer* frame_buffer = static_cast<VP9FrameBuffer*>(fb->priv); @@ -351,7 +352,7 @@ bound_decode_cb.Run(kDecodeError); return; } - // We might get a successfull VpxDecode but not a frame if only a partial + // We might get a successful VpxDecode but not a frame if only a partial // decode happened. if (video_frame.get()) output_cb_.Run(video_frame);
diff --git a/media/media.gyp b/media/media.gyp index 342a30f..5f0fd68b 100644 --- a/media/media.gyp +++ b/media/media.gyp
@@ -1550,7 +1550,7 @@ 'audio/mac/audio_low_latency_input_mac_unittest.cc', ], }], - ['chromeos==1', { + ['chromeos==1 or chromecast==1', { 'sources': [ 'audio/sounds/audio_stream_handler_unittest.cc', 'audio/sounds/sounds_manager_unittest.cc',
diff --git a/mojo/android/javatests/mojo_test_case.cc b/mojo/android/javatests/mojo_test_case.cc index 22a08ff6..631cf976 100644 --- a/mojo/android/javatests/mojo_test_case.cc +++ b/mojo/android/javatests/mojo_test_case.cc
@@ -30,10 +30,7 @@ namespace mojo { namespace android { -static void InitApplicationContext(JNIEnv* env, - const JavaParamRef<jobject>& jcaller, - const JavaParamRef<jobject>& context) { - base::android::InitApplicationContext(env, context); +static void Init(JNIEnv* env, const JavaParamRef<jobject>& jcaller) { base::InitAndroidTestMessageLoop(); }
diff --git a/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java b/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java index 4e96de27..3e81b7a8 100644 --- a/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java +++ b/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java
@@ -4,9 +4,9 @@ package org.chromium.mojo; -import android.content.Context; import android.test.InstrumentationTestCase; +import org.chromium.base.ContextUtils; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; @@ -27,7 +27,8 @@ super.setUp(); LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER) .ensureInitialized(getInstrumentation().getTargetContext()); - nativeInitApplicationContext(getInstrumentation().getTargetContext()); + ContextUtils.initApplicationContext(getInstrumentation().getTargetContext()); + nativeInit(); mTestEnvironmentPointer = nativeSetupTestEnvironment(); } @@ -54,7 +55,7 @@ nativeRunLoop(0); } - private native void nativeInitApplicationContext(Context context); + private native void nativeInit(); private native long nativeSetupTestEnvironment();
diff --git a/mojo/application/public/interfaces/BUILD.gn b/mojo/application/public/interfaces/BUILD.gn index f3958b5..1aa7fc5 100644 --- a/mojo/application/public/interfaces/BUILD.gn +++ b/mojo/application/public/interfaces/BUILD.gn
@@ -8,6 +8,7 @@ mojom("interfaces") { sources = [ "application.mojom", + "application_manager.mojom", "content_handler.mojom", "service_provider.mojom", "shell.mojom",
diff --git a/mojo/application/public/interfaces/application_manager.mojom b/mojo/application/public/interfaces/application_manager.mojom new file mode 100644 index 0000000..43edc81 --- /dev/null +++ b/mojo/application/public/interfaces/application_manager.mojom
@@ -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. + +module mojo.shell.mojom; + +import "mojo/application/public/interfaces/shell.mojom"; + +interface ApplicationManager { + // Instructs the ApplicationManager to create an instance for an existing + // process at the other end of |channel|, and perform applicable + // initialization. This assumes the target process will bind the other end of + // channel to an implementation of ChildController and bind an Application + // request there. + CreateInstanceForHandle(handle channel, + string url, + mojo.CapabilityFilter filter); +};
diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index dd79184..5ca21f3 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc
@@ -13,6 +13,7 @@ #include "base/message_loop/message_loop.h" #include "base/task_runner.h" #include "mojo/edk/embedder/embedder_internal.h" +#include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/process_delegate.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/system/configuration.h" @@ -20,6 +21,13 @@ #include "mojo/edk/system/message_pipe_dispatcher.h" #include "mojo/edk/system/platform_handle_dispatcher.h" +#if defined(OS_WIN) +#include "mojo/edk/system/child_token_serializer_win.h" +#include "mojo/edk/system/parent_token_serializer_state_win.h" +#include "mojo/edk/system/parent_token_serializer_win.h" +#include "mojo/edk/system/simple_token_serializer_win.h" +#endif + namespace mojo { namespace edk { @@ -49,6 +57,9 @@ namespace internal { // Declared in embedder_internal.h. +#if defined(OS_WIN) +TokenSerializer* g_token_serializer = nullptr; +#endif PlatformSupport* g_platform_support = nullptr; Core* g_core = nullptr; @@ -82,7 +93,40 @@ GetMutableConfiguration()->max_message_num_bytes = bytes; } +#if defined(OS_WIN) +void PreInitializeParentProcess() { + ParentTokenSerializerState::GetInstance(); +} + +void PreInitializeChildProcess() { + ChildTokenSerializer::GetInstance(); +} + +HANDLE ChildProcessLaunched(HANDLE child_process) { + PlatformChannelPair token_channel; + new ParentTokenSerializer(child_process, token_channel.PassServerHandle()); + return token_channel.PassClientHandle().release().handle; +} + +void ChildProcessLaunched(HANDLE child_process, HANDLE server_pipe) { + new ParentTokenSerializer( + child_process, ScopedPlatformHandle(PlatformHandle(server_pipe))); +} + +void SetParentPipeHandle(HANDLE pipe) { + ScopedPlatformHandle handle; + handle.reset(PlatformHandle(pipe)); + ChildTokenSerializer::GetInstance()-> + SetParentTokenSerializerHandle(handle.Pass()); +} +#endif + void Init() { +#if defined(OS_WIN) + if (!internal::g_token_serializer) + internal::g_token_serializer = new SimpleTokenSerializer; +#endif + DCHECK(!internal::g_platform_support); internal::g_platform_support = new SimplePlatformSupport();
diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h index 2bf9e15..52cca506 100644 --- a/mojo/edk/embedder/embedder.h +++ b/mojo/edk/embedder/embedder.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/process/process.h" #include "base/task_runner.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/system_impl_export.h" @@ -29,6 +30,27 @@ // Allows changing the default max message size. Must be called before Init. MOJO_SYSTEM_IMPL_EXPORT void SetMaxMessageSize(size_t bytes); +#if defined(OS_WIN) +// Must be called before Init in the parent (unsandboxed) process. +MOJO_SYSTEM_IMPL_EXPORT void PreInitializeParentProcess(); + +// Must be called before Init in the child (sandboxed) process. +MOJO_SYSTEM_IMPL_EXPORT void PreInitializeChildProcess(); + +// Called in the parent process for each child process that is launched. The +// returned handle must be sent to the child process which then calls +// SetParentPipeHandle. +MOJO_SYSTEM_IMPL_EXPORT HANDLE ChildProcessLaunched(HANDLE child_process); +// Like above, except used when the embedder establishes the pipe between the +// parent and child processes itself. +MOJO_SYSTEM_IMPL_EXPORT void ChildProcessLaunched(HANDLE child_process, + HANDLE server_pipe); + +// Should be called as early as possible in the child process with the handle +// that the parent received from ChildProcessLaunched. +MOJO_SYSTEM_IMPL_EXPORT void SetParentPipeHandle(HANDLE pipe); +#endif + // Must be called first, or just after setting configuration parameters, to // initialize the (global, singleton) system. MOJO_SYSTEM_IMPL_EXPORT void Init();
diff --git a/mojo/edk/embedder/embedder_internal.h b/mojo/edk/embedder/embedder_internal.h index 80d10f8..7acf5a1 100644 --- a/mojo/edk/embedder/embedder_internal.h +++ b/mojo/edk/embedder/embedder_internal.h
@@ -24,9 +24,15 @@ class Core; class PlatformSupport; class ProcessDelegate; +class TokenSerializer; namespace internal { +#if defined(OS_WIN) +// Instance of |TokenSerializer| to use. +extern TokenSerializer* g_token_serializer; +#endif + // Instance of |PlatformSupport| to use. extern PlatformSupport* g_platform_support;
diff --git a/mojo/edk/embedder/platform_channel_pair.h b/mojo/edk/embedder/platform_channel_pair.h index 7487837..80acc17c 100644 --- a/mojo/edk/embedder/platform_channel_pair.h +++ b/mojo/edk/embedder/platform_channel_pair.h
@@ -52,7 +52,9 @@ // platform differences in suppressing |SIGPIPE|. class MOJO_SYSTEM_IMPL_EXPORT PlatformChannelPair { public: - PlatformChannelPair(); + // If |client_is_blocking| is true, then the client handle only supports + // blocking reads and writes. The default is nonblocking. + PlatformChannelPair(bool client_is_blocking = false); ~PlatformChannelPair(); ScopedPlatformHandle PassServerHandle(); @@ -67,6 +69,10 @@ static ScopedPlatformHandle PassClientHandleFromParentProcess( const base::CommandLine& command_line); + // Like above, but gets the handle from the passed in string. + static ScopedPlatformHandle PassClientHandleFromParentProcessFromString( + const std::string& value); + // Prepares to pass the client channel to a new child process, to be launched // using |LaunchProcess()| (from base/launch.h). Modifies |*command_line| and // |*handle_passing_info| as needed. @@ -75,6 +81,10 @@ base::CommandLine* command_line, HandlePassingInformation* handle_passing_info) const; + // Like above, but returns a string instead of changing the command line. + std::string PrepareToPassClientHandleToChildProcessAsString( + HandlePassingInformation* handle_passing_info) const; + // To be called once the child process has been successfully launched, to do // any cleanup necessary. void ChildProcessLaunched();
diff --git a/mojo/edk/embedder/platform_channel_pair_posix.cc b/mojo/edk/embedder/platform_channel_pair_posix.cc index eaeac26..7ad1eea 100644 --- a/mojo/edk/embedder/platform_channel_pair_posix.cc +++ b/mojo/edk/embedder/platform_channel_pair_posix.cc
@@ -38,22 +38,24 @@ } // namespace -PlatformChannelPair::PlatformChannelPair() { - // Create the Unix domain socket and set the ends to nonblocking. +PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { + // Create the Unix domain socket. int fds[2]; // TODO(vtl): Maybe fail gracefully if |socketpair()| fails. PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0); // Store a common id in the SO_PEEK_OFF option (which we don't use since we - // don't peak) as a way of determining later if two sockets are connected to + // don't peek) as a way of determining later if two sockets are connected to // each other. int identifier = base::RandInt(kint32min, kint32max); setsockopt(fds[0], SOL_SOCKET, SO_PEEK_OFF, &identifier, sizeof(identifier)); setsockopt(fds[1], SOL_SOCKET, SO_PEEK_OFF, &identifier, sizeof(identifier)); + // Set the ends to nonblocking. PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0); - PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0); + if (!client_is_blocking) + PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0); #if defined(OS_MACOSX) // This turns off |SIGPIPE| when writing to a closed socket (causing it to @@ -77,9 +79,15 @@ const base::CommandLine& command_line) { std::string client_fd_string = command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); + return PassClientHandleFromParentProcessFromString(client_fd_string); +} + +ScopedPlatformHandle +PlatformChannelPair::PassClientHandleFromParentProcessFromString( + const std::string& value) { int client_fd = -1; - if (client_fd_string.empty() || - !base::StringToInt(client_fd_string, &client_fd) || + if (value.empty() || + !base::StringToInt(value, &client_fd) || client_fd < base::GlobalDescriptors::kBaseDescriptor) { LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; return ScopedPlatformHandle(); @@ -92,6 +100,24 @@ base::CommandLine* command_line, base::FileHandleMappingVector* handle_passing_info) const { DCHECK(command_line); + + // Log a warning if the command line already has the switch, but "clobber" it + // anyway, since it's reasonably likely that all the switches were just copied + // from the parent. + LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) + << "Child command line already has switch --" + << kMojoPlatformChannelHandleSwitch << "=" + << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); + // (Any existing switch won't actually be removed from the command line, but + // the last one appended takes precedence.) + command_line->AppendSwitchASCII( + kMojoPlatformChannelHandleSwitch, + PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); +} + +std::string +PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( + HandlePassingInformation* handle_passing_info) const { DCHECK(handle_passing_info); // This is an arbitrary sanity check. (Note that this guarantees that the loop // below will terminate sanely.) @@ -108,17 +134,7 @@ handle_passing_info->push_back( std::pair<int, int>(client_handle_.get().fd, target_fd)); - // Log a warning if the command line already has the switch, but "clobber" it - // anyway, since it's reasonably likely that all the switches were just copied - // from the parent. - LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) - << "Child command line already has switch --" - << kMojoPlatformChannelHandleSwitch << "=" - << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - // (Any existing switch won't actually be removed from the command line, but - // the last one appended takes precedence.) - command_line->AppendSwitchASCII(kMojoPlatformChannelHandleSwitch, - base::IntToString(target_fd)); + return base::IntToString(target_fd); } } // namespace edk
diff --git a/mojo/edk/embedder/platform_channel_pair_win.cc b/mojo/edk/embedder/platform_channel_pair_win.cc index f7788ad..f523ade 100644 --- a/mojo/edk/embedder/platform_channel_pair_win.cc +++ b/mojo/edk/embedder/platform_channel_pair_win.cc
@@ -29,10 +29,10 @@ } // namespace -PlatformChannelPair::PlatformChannelPair() { +PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { std::wstring pipe_name = GeneratePipeName(); - const DWORD kOpenMode = + DWORD kOpenMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE; const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE; server_handle_.reset(PlatformHandle( @@ -47,8 +47,9 @@ const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE; // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate // the client. - const DWORD kFlags = - SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED; + DWORD kFlags = SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS; + if (!client_is_blocking) + kFlags |= FILE_FLAG_OVERLAPPED; // Allow the handle to be inherited by child processes. SECURITY_ATTRIBUTES security_attributes = { sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; @@ -70,10 +71,15 @@ const base::CommandLine& command_line) { std::string client_handle_string = command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); + return PassClientHandleFromParentProcessFromString(client_handle_string); +} +ScopedPlatformHandle +PlatformChannelPair::PassClientHandleFromParentProcessFromString( + const std::string& value) { int client_handle_value = 0; - if (client_handle_string.empty() || - !base::StringToInt(client_handle_string, &client_handle_value)) { + if (value.empty() || + !base::StringToInt(value, &client_handle_value)) { LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; return ScopedPlatformHandle(); } @@ -86,11 +92,6 @@ base::CommandLine* command_line, base::HandlesToInheritVector* handle_passing_info) const { DCHECK(command_line); - DCHECK(handle_passing_info); - DCHECK(client_handle_.is_valid()); - - if (base::win::GetVersion() >= base::win::VERSION_VISTA) - handle_passing_info->push_back(client_handle_.get().handle); // Log a warning if the command line already has the switch, but "clobber" it // anyway, since it's reasonably likely that all the switches were just copied @@ -103,7 +104,19 @@ // the last one appended takes precedence.) command_line->AppendSwitchASCII( kMojoPlatformChannelHandleSwitch, - base::IntToString(HandleToLong(client_handle_.get().handle))); + PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); +} + +std::string +PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( + HandlePassingInformation* handle_passing_info) const { + DCHECK(handle_passing_info); + DCHECK(client_handle_.is_valid()); + + if (base::win::GetVersion() >= base::win::VERSION_VISTA) + handle_passing_info->push_back(client_handle_.get().handle); + + return base::IntToString(HandleToLong(client_handle_.get().handle)); } } // namespace edk
diff --git a/mojo/edk/embedder/test_embedder.cc b/mojo/edk/embedder/test_embedder.cc index b33ea7be..9e82a4e 100644 --- a/mojo/edk/embedder/test_embedder.cc +++ b/mojo/edk/embedder/test_embedder.cc
@@ -12,6 +12,10 @@ #include "mojo/edk/system/core.h" #include "mojo/edk/system/handle_table.h" +#if defined(OS_WIN) +#include "mojo/edk/system/token_serializer_win.h" +#endif + namespace mojo { namespace edk { @@ -47,6 +51,12 @@ delete internal::g_platform_support; internal::g_platform_support = nullptr; +#if defined(OS_WIN) + CHECK(internal::g_token_serializer); + delete internal::g_token_serializer; + internal::g_token_serializer = nullptr; +#endif + return rv; }
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index f0c1e82..7b25702 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn
@@ -31,6 +31,8 @@ "awakable.h", "awakable_list.cc", "awakable_list.h", + "child_token_serializer_win.cc", + "child_token_serializer_win.h", "configuration.cc", "configuration.h", "core.cc", @@ -55,6 +57,10 @@ "message_pipe_dispatcher.cc", "message_pipe_dispatcher.h", "options_validation.h", + "parent_token_serializer_state_win.cc", + "parent_token_serializer_state_win.h", + "parent_token_serializer_win.cc", + "parent_token_serializer_win.h", "platform_handle_dispatcher.cc", "platform_handle_dispatcher.h", "raw_channel.cc", @@ -65,6 +71,10 @@ "shared_buffer_dispatcher.h", "simple_dispatcher.cc", "simple_dispatcher.h", + "simple_token_serializer_win.cc", + "simple_token_serializer_win.h", + "token_serializer_messages_win.h", + "token_serializer_win.h", "transport_data.cc", "transport_data.h", "waiter.cc",
diff --git a/mojo/edk/system/child_token_serializer_win.cc b/mojo/edk/system/child_token_serializer_win.cc new file mode 100644 index 0000000..bbbbea41 --- /dev/null +++ b/mojo/edk/system/child_token_serializer_win.cc
@@ -0,0 +1,124 @@ +// Copyright 2015 The Chromium Authors. 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/edk/system/child_token_serializer_win.h" + +#include "base/logging.h" +#include "mojo/edk/embedder/embedder_internal.h" +#include "mojo/edk/system/token_serializer_messages_win.h" + +namespace mojo { +namespace edk { + +ChildTokenSerializer* ChildTokenSerializer::GetInstance() { + return base::Singleton< + ChildTokenSerializer, + base::LeakySingletonTraits<ChildTokenSerializer>>::get(); +} + +void ChildTokenSerializer::SetParentTokenSerializerHandle( + ScopedPlatformHandle handle) { + handle_ = handle.Pass(); + lock_.Unlock(); +} + +void ChildTokenSerializer::CreatePlatformChannelPair( + ScopedPlatformHandle* server, ScopedPlatformHandle* client) { + TokenSerializerMessage message; + message.size = kTokenSerializerMessageHeaderSize; + message.id = CREATE_PLATFORM_CHANNEL_PAIR; + + uint32_t response_size = 2 * sizeof(HANDLE); + HANDLE handles[2]; + if (WriteAndReadResponse(&message, handles, response_size)) { + server->reset(PlatformHandle(handles[0])); + client->reset(PlatformHandle(handles[1])); + } +} + +void ChildTokenSerializer::HandleToToken(const PlatformHandle* platform_handles, + size_t count, + uint64_t* tokens) { + uint32_t size = kTokenSerializerMessageHeaderSize + + static_cast<int>(count) * sizeof(HANDLE); + std::vector<char> message_buffer(size); + TokenSerializerMessage* message = + reinterpret_cast<TokenSerializerMessage*>(&message_buffer[0]); + message->size = size; + message->id = HANDLE_TO_TOKEN; + for (size_t i = 0; i < count; ++i) + message->handles[i] = platform_handles[i].handle; + + uint32_t response_size = static_cast<int>(count) * sizeof(uint64_t); + WriteAndReadResponse(message, tokens, response_size); +} + +void ChildTokenSerializer::TokenToHandle(const uint64_t* tokens, + size_t count, + PlatformHandle* handles) { + uint32_t size = kTokenSerializerMessageHeaderSize + + static_cast<int>(count) * sizeof(uint64_t); + std::vector<char> message_buffer(size); + TokenSerializerMessage* message = + reinterpret_cast<TokenSerializerMessage*>(&message_buffer[0]); + message->size = size; + message->id = TOKEN_TO_HANDLE; + memcpy(&message->tokens[0], tokens, count * sizeof(uint64_t)); + + std::vector<HANDLE> handles_temp(count); + uint32_t response_size = + static_cast<uint32_t>(handles_temp.size()) * sizeof(HANDLE); + if (WriteAndReadResponse(message, &handles_temp[0], response_size)) { + for (uint32_t i = 0; i < count; ++i) + handles[i].handle = handles_temp[i]; + } +} + +ChildTokenSerializer::ChildTokenSerializer() { + DCHECK(!internal::g_token_serializer); + internal::g_token_serializer = this; + // Block any threads from calling this until we have a pipe to the parent. + lock_.Lock(); +} + +ChildTokenSerializer::~ChildTokenSerializer() { +} + +bool ChildTokenSerializer::WriteAndReadResponse(TokenSerializerMessage* message, + void* response, + uint32_t response_size) { + lock_.Lock(); + CHECK(handle_.is_valid()); + + bool result = true; + DWORD bytes_written = 0; + // This will always write in one chunk per + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150.aspx. + BOOL rv = WriteFile(handle_.get().handle, message, message->size, + &bytes_written, NULL); + if (!rv || bytes_written != message->size) { + LOG(ERROR) << "Child token serializer couldn't write message."; + result = false; + } else { + while (response_size) { + DWORD bytes_read = 0; + rv = ReadFile(handle_.get().handle, response, response_size, &bytes_read, + NULL); + if (!rv) { + LOG(ERROR) << "Child token serializer couldn't read result."; + result = false; + break; + } + response_size -= bytes_read; + response = static_cast<char*>(response) + bytes_read; + } + } + + lock_.Unlock(); + + return result; +} + +} // namespace edk +} // namespace mojo
diff --git a/mojo/edk/system/child_token_serializer_win.h b/mojo/edk/system/child_token_serializer_win.h new file mode 100644 index 0000000..abc9c8c7 --- /dev/null +++ b/mojo/edk/system/child_token_serializer_win.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 MOJO_EDK_SYSTEM_CHILD_TOKEN_SERIALIZER_WIN_H_ +#define MOJO_EDK_SYSTEM_CHILD_TOKEN_SERIALIZER_WIN_H_ + +#include "base/memory/singleton.h" +#include "base/synchronization/lock_impl.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/edk/system/system_impl_export.h" +#include "mojo/edk/system/token_serializer_win.h" + +namespace mojo { +namespace edk { +struct TokenSerializerMessage; + +// An implementation of TokenSerializer used in (sandboxed) child processes. It +// talks over sync IPCs to the (unsandboxed) parent process (specifically, +// ParentTokenSerializer) to convert handles to tokens and vice versa. +class MOJO_SYSTEM_IMPL_EXPORT ChildTokenSerializer : public TokenSerializer { + public: + static ChildTokenSerializer* GetInstance(); + + // Passes the platform handle that is used to talk to ParentTokenSerializer. + void SetParentTokenSerializerHandle(ScopedPlatformHandle handle); + + // TokenSerializer implementation: + void CreatePlatformChannelPair(ScopedPlatformHandle* server, + ScopedPlatformHandle* client) override; + void HandleToToken(const PlatformHandle* platform_handles, + size_t count, + uint64_t* tokens) override; + void TokenToHandle(const uint64_t* tokens, + size_t count, + PlatformHandle* handles) override; + + private: + friend struct base::DefaultSingletonTraits<ChildTokenSerializer>; + + ChildTokenSerializer(); + ~ChildTokenSerializer() override; + + // Helper method to write the given message and read back the result. + bool WriteAndReadResponse(TokenSerializerMessage* message, + void* response, + uint32_t response_size); + + // Guards access to below. + // We use LockImpl instead of Lock because the latter adds thread checking + // that we don't want (since we lock in the constructor and unlock on another + // thread. + base::internal::LockImpl lock_; + ScopedPlatformHandle handle_; +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_CHILD_TOKEN_SERIALIZER_WIN_H_
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index ac513da7..af9d151c 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/time/time.h" +#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/embedder/platform_support.h" @@ -24,6 +25,10 @@ #include "mojo/public/c/system/macros.h" #include "mojo/public/cpp/system/macros.h" +#if defined(OS_WIN) +#include "mojo/edk/system/token_serializer_win.h" +#endif + namespace mojo { namespace edk { @@ -204,11 +209,19 @@ return MOJO_RESULT_RESOURCE_EXHAUSTED; } + ScopedPlatformHandle server_handle, client_handle; +#if defined(OS_WIN) + internal::g_token_serializer->CreatePlatformChannelPair( + &server_handle, &client_handle); +#else PlatformChannelPair channel_pair; - dispatcher0->Init(channel_pair.PassServerHandle(), nullptr, 0u, nullptr, 0u, - nullptr, nullptr); - dispatcher1->Init(channel_pair.PassClientHandle(), nullptr, 0u, nullptr, 0u, - nullptr, nullptr); + server_handle = channel_pair.PassServerHandle(); + client_handle = channel_pair.PassClientHandle(); +#endif + dispatcher0->Init(server_handle.Pass(), nullptr, 0u, nullptr, 0u, nullptr, + nullptr); + dispatcher1->Init(client_handle.Pass(), nullptr, 0u, nullptr, 0u, nullptr, + nullptr); *message_pipe_handle0 = handle_pair.first; *message_pipe_handle1 = handle_pair.second; @@ -364,9 +377,17 @@ } DCHECK_NE(handle_pair.second, MOJO_HANDLE_INVALID); + ScopedPlatformHandle server_handle, client_handle; +#if defined(OS_WIN) + internal::g_token_serializer->CreatePlatformChannelPair( + &server_handle, &client_handle); +#else PlatformChannelPair channel_pair; - producer_dispatcher->Init(channel_pair.PassServerHandle(), nullptr, 0u); - consumer_dispatcher->Init(channel_pair.PassClientHandle(), nullptr, 0u); + server_handle = channel_pair.PassServerHandle(); + client_handle = channel_pair.PassClientHandle(); +#endif + producer_dispatcher->Init(server_handle.Pass(), nullptr, 0u); + consumer_dispatcher->Init(client_handle.Pass(), nullptr, 0u); *data_pipe_producer_handle = handle_pair.first; *data_pipe_consumer_handle = handle_pair.second;
diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc index e3e67ab..fb3ce4e 100644 --- a/mojo/edk/system/message_pipe_dispatcher.cc +++ b/mojo/edk/system/message_pipe_dispatcher.cc
@@ -16,6 +16,10 @@ #include "mojo/edk/system/options_validation.h" #include "mojo/edk/system/transport_data.h" +#if defined(OS_WIN) +#include "mojo/edk/system/token_serializer_win.h" +#endif + namespace mojo { namespace edk { @@ -38,7 +42,7 @@ size_t serialized_read_buffer_size; size_t serialized_write_buffer_size; - size_t serialized_messagage_queue_size; + size_t serialized_message_queue_size; // These are the FDs required as part of serializing channel_ and // message_queue_. This is only used on POSIX. @@ -161,9 +165,9 @@ return Type::MESSAGE_PIPE; } +#if defined(OS_WIN) // TODO(jam): this is copied from RawChannelWin till I figure out what's the -// best way we want to share this. Need to also consider posix which does -// require access to the RawChannel. +// best way we want to share this. // Since this is used for serialization of messages read/written to a MP that // aren't consumed by Mojo primitives yet, there could be an unbounded number of // them when a MP is being sent. As a result, even for POSIX we will probably @@ -173,41 +177,16 @@ ScopedPlatformHandleVectorPtr GetReadPlatformHandles( size_t num_platform_handles, const void* platform_handle_table) { - // TODO(jam): this code will have to be updated once it's used in a sandbox - // and the receiving process doesn't have duplicate permission for the - // receiver. Once there's a broker and we have a connection to it (possibly - // through ConnectionManager), then we can make a sync IPC to it here to get a - // token for this handle, and it will duplicate the handle to is process. Then - // we pass the token to the receiver, which will then make a sync call to the - // broker to get a duplicated handle. This will also allow us to avoid leaks - // of the handle if the receiver dies, since the broker can notice that. - DCHECK_GT(num_platform_handles, 0u); ScopedPlatformHandleVectorPtr rv(new PlatformHandleVector()); + rv->resize(num_platform_handles); -#if defined(OS_WIN) - const char* serialization_data = - static_cast<const char*>(platform_handle_table); - for (size_t i = 0; i < num_platform_handles; i++) { - DWORD pid = *reinterpret_cast<const DWORD*>(serialization_data); - serialization_data += sizeof(DWORD); - HANDLE source_handle = *reinterpret_cast<const HANDLE*>(serialization_data); - serialization_data += sizeof(HANDLE); - base::Process sender = - base::Process::OpenWithAccess(pid, PROCESS_DUP_HANDLE); - DCHECK(sender.IsValid()); - HANDLE target_handle = NULL; - BOOL dup_result = - DuplicateHandle(sender.Handle(), source_handle, - base::GetCurrentProcessHandle(), &target_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); - DCHECK(dup_result); - rv->push_back(PlatformHandle(target_handle)); - } -#else - NOTREACHED() << "TODO(jam): implement"; -#endif + const uint64_t* tokens = + static_cast<const uint64_t*>(platform_handle_table); + internal::g_token_serializer->TokenToHandle( + tokens, num_platform_handles, &rv->at(0)); return rv.Pass(); } +#endif scoped_refptr<MessagePipeDispatcher> MessagePipeDispatcher::Deserialize( const void* source, @@ -223,7 +202,7 @@ if (serialization->shared_memory_size != (serialization->serialized_read_buffer_size + serialization->serialized_write_buffer_size + - serialization->serialized_messagage_queue_size)) { + serialization->serialized_message_queue_size)) { LOG(ERROR) << "Invalid serialized message pipe dispatcher (bad struct)"; return nullptr; } @@ -260,9 +239,9 @@ serialization->serialized_write_buffer_size; buffer += serialized_write_buffer_size; } - if (serialization->serialized_messagage_queue_size) { + if (serialization->serialized_message_queue_size) { message_queue_data = buffer; - message_queue_size = serialization->serialized_messagage_queue_size; + message_queue_size = serialization->serialized_message_queue_size; buffer += message_queue_size; } } @@ -459,18 +438,13 @@ message->transport_data()->platform_handles(); if (all_platform_handles) { #if defined(OS_WIN) - char* serialization_data = + uint64_t* tokens = reinterpret_cast<uint64_t*>( static_cast<char*>(message->transport_data()->buffer()) + - message->transport_data()->platform_handle_table_offset(); - DWORD current_process_id = base::GetCurrentProcId(); - for (size_t i = 0; i < all_platform_handles->size(); i++) { - *reinterpret_cast<DWORD*>(serialization_data) = current_process_id; - serialization_data += sizeof(DWORD); - *reinterpret_cast<HANDLE*>(serialization_data) = - all_platform_handles->at(i).handle; - serialization_data += sizeof(HANDLE); + message->transport_data()->platform_handle_table_offset()); + internal::g_token_serializer->HandleToToken( + &all_platform_handles->at(0), all_platform_handles->size(), tokens); + for (size_t i = 0; i < all_platform_handles->size(); i++) all_platform_handles->at(i) = PlatformHandle(); - } #else for (size_t i = 0; i < all_platform_handles->size(); i++) { serialized_fds_.push_back(all_platform_handles->at(i).fd); @@ -700,13 +674,13 @@ serialization->write_error = write_error_; serialization->serialized_read_buffer_size = serialized_read_buffer_.size(); serialization->serialized_write_buffer_size = serialized_write_buffer_.size(); - serialization->serialized_messagage_queue_size = + serialization->serialized_message_queue_size = serialized_message_queue_.size(); serialization->shared_memory_size = static_cast<uint32_t>( serialization->serialized_read_buffer_size + serialization->serialized_write_buffer_size + - serialization->serialized_messagage_queue_size); + serialization->serialized_message_queue_size); if (serialization->shared_memory_size) { scoped_refptr<PlatformSharedBuffer> shared_buffer( internal::g_platform_support->CreateSharedBuffer(
diff --git a/mojo/edk/system/parent_token_serializer_state_win.cc b/mojo/edk/system/parent_token_serializer_state_win.cc new file mode 100644 index 0000000..ccd3cbe --- /dev/null +++ b/mojo/edk/system/parent_token_serializer_state_win.cc
@@ -0,0 +1,75 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/parent_token_serializer_state_win.h" + +#include "base/rand_util.h" +#include "mojo/edk/embedder/embedder_internal.h" +#include "mojo/edk/embedder/platform_channel_pair.h" + +namespace mojo { +namespace edk { + +ParentTokenSerializerState* ParentTokenSerializerState::GetInstance() { + return base::Singleton< + ParentTokenSerializerState, + base::LeakySingletonTraits<ParentTokenSerializerState>>::get(); +} + +void ParentTokenSerializerState::CreatePlatformChannelPair( + ScopedPlatformHandle* server, ScopedPlatformHandle* client) { + PlatformChannelPair channel_pair; + *server = channel_pair.PassServerHandle(); + *client = channel_pair.PassClientHandle(); +} + +void ParentTokenSerializerState::HandleToToken( + const PlatformHandle* platform_handles, + size_t count, + uint64_t* tokens) { + base::AutoLock auto_locker(lock_); + for (size_t i = 0; i < count; ++i) { + if (platform_handles[i].is_valid()) { + uint64_t token; + do { + token = base::RandUint64(); + } while (!token || token_map_.find(token) != token_map_.end()); + tokens[i] = token; + token_map_[tokens[i]] = platform_handles[i].handle; + } else { + DLOG(WARNING) << "ParentTokenSerializerState got invalid handle."; + tokens[i] = 0; + } + } +} + +void ParentTokenSerializerState::TokenToHandle( + const uint64_t* tokens, + size_t count, + PlatformHandle* handles) { + base::AutoLock auto_locker(lock_); + for (size_t i = 0; i < count; ++i) { + auto it = token_map_.find(tokens[i]); + if (it == token_map_.end()) { + DLOG(WARNING) << "TokenToHandle didn't find token."; + } else { + handles[i].handle = it->second; + token_map_.erase(it); + } + } +} + +ParentTokenSerializerState::ParentTokenSerializerState() + : token_serialize_thread_("Token Serializer Watcher") { + base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); + token_serialize_thread_.StartWithOptions(options); + DCHECK(!internal::g_token_serializer); + internal::g_token_serializer = this; +} + +ParentTokenSerializerState::~ParentTokenSerializerState() { +} + +} // namespace edk +} // namespace mojo
diff --git a/mojo/edk/system/parent_token_serializer_state_win.h b/mojo/edk/system/parent_token_serializer_state_win.h new file mode 100644 index 0000000..c1db1cf --- /dev/null +++ b/mojo/edk/system/parent_token_serializer_state_win.h
@@ -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. + +#ifndef MOJO_EDK_SYSTEM_PARENT_TOKEN_SERIALIZER_STATE_WIN_H_ +#define MOJO_EDK_SYSTEM_PARENT_TOKEN_SERIALIZER_STATE_WIN_H_ + +#include "base/compiler_specific.h" +#include "base/containers/hash_tables.h" +#include "base/memory/singleton.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/edk/system/system_impl_export.h" +#include "mojo/edk/system/token_serializer_win.h" + +namespace mojo { +namespace edk { + +// Common state that has to live in a parent process on Windows. There is one +// instance of this class in the parent process. This class also implements the +// TokenSerializer interface for use by code in the parent process. +class MOJO_SYSTEM_IMPL_EXPORT ParentTokenSerializerState + : NON_EXPORTED_BASE(public TokenSerializer) { + public: + static ParentTokenSerializerState* GetInstance(); + + // TokenSerializer implementation. + void CreatePlatformChannelPair(ScopedPlatformHandle* server, + ScopedPlatformHandle* client) override; + void HandleToToken(const PlatformHandle* platform_handles, + size_t count, + uint64_t* tokens) override; + void TokenToHandle(const uint64_t* tokens, + size_t count, + PlatformHandle* handles) override; + + scoped_refptr<base::TaskRunner> token_serialize_thread() { + return token_serialize_thread_.task_runner(); + } + + private: + friend struct base::DefaultSingletonTraits<ParentTokenSerializerState>; + + ParentTokenSerializerState(); + ~ParentTokenSerializerState() override; + + // A separate thread to handle sync IPCs from child processes for exchanging + // platform handles with tokens. We use a separate thread because latency is + // very sensitive (since any time a pipe is created or sent, a child process + // makes a sync call to this class). + base::Thread token_serialize_thread_; + + // Used in the parent (unsandboxed) process to hold a mapping between HANDLES + // and tokens. When a child process wants to send a HANDLE to another process, + // it exchanges it to a token and then the other process exchanges that token + // back to a HANDLE. + base::Lock lock_; // Guards access to below. + base::hash_map<uint64_t, HANDLE> token_map_; +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_PARENT_TOKEN_SERIALIZER_STATE_WIN_H_
diff --git a/mojo/edk/system/parent_token_serializer_win.cc b/mojo/edk/system/parent_token_serializer_win.cc new file mode 100644 index 0000000..ea2cb8d --- /dev/null +++ b/mojo/edk/system/parent_token_serializer_win.cc
@@ -0,0 +1,176 @@ +// Copyright 2015 The Chromium Authors. 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/edk/system/parent_token_serializer_win.h" + +#include "base/bind.h" +#include "base/lazy_instance.h" +#include "mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/system/configuration.h" +#include "mojo/edk/system/parent_token_serializer_state_win.h" +#include "mojo/edk/system/token_serializer_messages_win.h" + +namespace mojo { +namespace edk { + +namespace { +static const int kDefaultReadBufferSize = 256; +} + +ParentTokenSerializer::ParentTokenSerializer(HANDLE child_process, + ScopedPlatformHandle pipe) + : child_process_(child_process), + pipe_(pipe.Pass()), + num_bytes_read_(0) { + memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); + read_context_.handler = this; + memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); + write_context_.handler = this; + + read_data_.resize(kDefaultReadBufferSize); + ParentTokenSerializerState::GetInstance()->token_serialize_thread()->PostTask( + FROM_HERE, + base::Bind(&ParentTokenSerializer::RegisterIOHandler, + base::Unretained(this))); +} + +ParentTokenSerializer::~ParentTokenSerializer() { +} + +void ParentTokenSerializer::RegisterIOHandler() { + base::MessageLoopForIO::current()->RegisterIOHandler( + pipe_.get().handle, this); + BeginRead(); +} + +void ParentTokenSerializer::BeginRead() { + BOOL rv = ReadFile(pipe_.get().handle, &read_data_[num_bytes_read_], + static_cast<int>(read_data_.size() - num_bytes_read_), + nullptr, &read_context_.overlapped); + if (rv || GetLastError() == ERROR_IO_PENDING) + return; + + if (rv == ERROR_BROKEN_PIPE) { + delete this; + return; + } + + NOTREACHED() << "Unknown error in ParentTokenSerializer " << rv; +} + +void ParentTokenSerializer::OnIOCompleted( + base::MessageLoopForIO::IOContext* context, + DWORD bytes_transferred, + DWORD error) { + if (context != &read_context_) + return; + + if (error == ERROR_BROKEN_PIPE) { + delete this; + return; // Child process exited or crashed. + } + + if (error != ERROR_SUCCESS) { + NOTREACHED() << "Error " << error << " in ParentTokenSerializer."; + delete this; + return; + } + + num_bytes_read_ += bytes_transferred; + CHECK_GE(num_bytes_read_, sizeof(uint32_t)); + TokenSerializerMessage* message = + reinterpret_cast<TokenSerializerMessage*>(&read_data_[0]); + if (num_bytes_read_ < message->size) { + read_data_.resize(message->size); + BeginRead(); + return; + } + + if (message->id == CREATE_PLATFORM_CHANNEL_PAIR) { + PlatformChannelPair channel_pair; + uint32_t response_size = 2 * sizeof(HANDLE); + write_data_.resize(response_size); + HANDLE* handles = reinterpret_cast<HANDLE*>(&write_data_[0]); + handles[0] = DuplicateToChild( + channel_pair.PassServerHandle().release().handle); + handles[1] = DuplicateToChild( + channel_pair.PassClientHandle().release().handle); + } else if (message->id == HANDLE_TO_TOKEN) { + uint32_t count = + (message->size - kTokenSerializerMessageHeaderSize) / sizeof(HANDLE); + if (count > GetConfiguration().max_message_num_handles) { + NOTREACHED() << "Too many handles from child process. Closing channel."; + delete this; + return; + } + uint32_t response_size = count * sizeof(uint64_t); + write_data_.resize(response_size); + uint64_t* tokens = reinterpret_cast<uint64_t*>(&write_data_[0]); + std::vector<PlatformHandle> duplicated_handles(count); + for (uint32_t i = 0; i < count; ++i) { + duplicated_handles[i] = + PlatformHandle(DuplicateFromChild(message->handles[i])); + } + ParentTokenSerializerState::GetInstance()->HandleToToken( + &duplicated_handles[0], count, tokens); + } else if (message->id == TOKEN_TO_HANDLE) { + uint32_t count = + (message->size - kTokenSerializerMessageHeaderSize) / + sizeof(uint64_t); + if (count > GetConfiguration().max_message_num_handles) { + NOTREACHED() << "Too many tokens from child process. Closing channel."; + delete this; + return; + } + uint32_t response_size = count * sizeof(HANDLE); + write_data_.resize(response_size); + HANDLE* handles = reinterpret_cast<HANDLE*>(&write_data_[0]); + std::vector<PlatformHandle> temp_handles(count); + ParentTokenSerializerState::GetInstance()->TokenToHandle( + &message->tokens[0], count, &temp_handles[0]); + for (uint32_t i = 0; i < count; ++i) { + if (temp_handles[i].is_valid()) { + handles[i] = DuplicateToChild(temp_handles[i].handle); + } else { + NOTREACHED() << "Unknown token"; + handles[i] = INVALID_HANDLE_VALUE; + } + } + } else { + NOTREACHED() << "Unknown command. Stopping reading."; + delete this; + return; + } + + BOOL rv = WriteFile(pipe_.get().handle, &write_data_[0], + static_cast<int>(write_data_.size()), NULL, + &write_context_.overlapped); + DCHECK(rv || GetLastError() == ERROR_IO_PENDING); + + // Start reading again. + num_bytes_read_ = 0; + BeginRead(); +} + + +HANDLE ParentTokenSerializer::DuplicateToChild(HANDLE handle) { + HANDLE rv = INVALID_HANDLE_VALUE; + BOOL result = DuplicateHandle(base::GetCurrentProcessHandle(), handle, + child_process_, &rv, 0, FALSE, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); + DCHECK(result); + return rv; +} + +HANDLE ParentTokenSerializer::DuplicateFromChild(HANDLE handle) { + HANDLE rv = INVALID_HANDLE_VALUE; + BOOL result = DuplicateHandle(child_process_, handle, + base::GetCurrentProcessHandle(), &rv, 0, FALSE, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); + DCHECK(result); + return rv; +} + +} // namespace edk +} // namespace mojo
diff --git a/mojo/edk/system/parent_token_serializer_win.h b/mojo/edk/system/parent_token_serializer_win.h new file mode 100644 index 0000000..ec86a77 --- /dev/null +++ b/mojo/edk/system/parent_token_serializer_win.h
@@ -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. + +#ifndef MOJO_EDK_SYSTEM_PARENT_TOKEN_SERIALIZER_WIN_H_ +#define MOJO_EDK_SYSTEM_PARENT_TOKEN_SERIALIZER_WIN_H_ + +#include <vector> + +#include "base/compiler_specific.h" +#include "base/message_loop/message_loop.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/edk/system/system_impl_export.h" + +namespace mojo { +namespace edk { + +// Responds to requests from a child process to exchange handles to tokens and +// vice versa. There is one object of this class per child process host object. +// This object will delete itself when it notices that the pipe is broken. +class MOJO_SYSTEM_IMPL_EXPORT ParentTokenSerializer + : NON_EXPORTED_BASE(public base::MessageLoopForIO::IOHandler) { + public: + // |child_process| is a handle to the child process. It's not owned by this + // class but is guaranteed to be alive as long as the child process is + // running. |pipe| is a handle to the communication pipe to the child process, + // which is generated inside mojo::edk::ChildProcessLaunched. It is owned by + // this class. + ParentTokenSerializer(HANDLE child_process, ScopedPlatformHandle pipe); + + private: + ~ParentTokenSerializer() override; + + void RegisterIOHandler(); + void BeginRead(); + + void OnIOCompleted(base::MessageLoopForIO::IOContext* context, + DWORD bytes_transferred, + DWORD error) override; + + // Helper wrappers around DuplicateHandle. + HANDLE DuplicateToChild(HANDLE handle); + HANDLE DuplicateFromChild(HANDLE handle); + + HANDLE child_process_; + ScopedPlatformHandle pipe_; + base::MessageLoopForIO::IOContext read_context_; + base::MessageLoopForIO::IOContext write_context_; + + std::vector<char> read_data_; + // How many bytes in read_data_ we already read. + uint32_t num_bytes_read_; + std::vector<char> write_data_; +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_PARENT_TOKEN_SERIALIZER_WIN_H_
diff --git a/mojo/edk/system/raw_channel.cc b/mojo/edk/system/raw_channel.cc index 6f560d6..a7faead 100644 --- a/mojo/edk/system/raw_channel.cc +++ b/mojo/edk/system/raw_channel.cc
@@ -222,6 +222,7 @@ return; initialized_ = true; internal::ChannelStarted(); + base::MessageLoop::current()->AddDestructionObserver(this); OnInit(); @@ -286,8 +287,10 @@ OnShutdownNoLock(read_buffer_.Pass(), write_buffer_.Pass()); } - if (initialized_) + if (initialized_) { internal::ChannelShutdown(); + base::MessageLoop::current()->RemoveDestructionObserver(this); + } delete this; return; } @@ -715,9 +718,14 @@ } void RawChannel::CallOnReadCompleted(IOResult io_result, size_t bytes_read) { - base::AutoLock locker(read_lock()); + base::AutoLock locker(read_lock_); OnReadCompletedNoLock(io_result, bytes_read); } +void RawChannel::WillDestroyCurrentMessageLoop() { + base::AutoLock locker(read_lock_); + OnReadCompletedNoLock(IO_FAILED_SHUTDOWN, 0); +} + } // namespace edk } // namespace mojo
diff --git a/mojo/edk/system/raw_channel.h b/mojo/edk/system/raw_channel.h index 07b7881..b261a792 100644 --- a/mojo/edk/system/raw_channel.h +++ b/mojo/edk/system/raw_channel.h
@@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/message_loop/message_loop.h" #include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/embedder/scoped_platform_handle.h" @@ -35,7 +36,8 @@ // With the exception of |WriteMessage()|, this class is thread-unsafe (and in // general its methods should only be used on the I/O thread, i.e., the thread // on which |Init()| is called). -class MOJO_SYSTEM_IMPL_EXPORT RawChannel { +class MOJO_SYSTEM_IMPL_EXPORT RawChannel : + public base::MessageLoop::DestructionObserver { public: // The |Delegate| is only accessed on the same thread as the message loop @@ -239,11 +241,11 @@ // Shutdown must be called on the IO thread. This object deletes itself once // it's flushed all pending writes and insured that the other side of the pipe // read them. - virtual ~RawChannel(); + ~RawChannel() override; // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT // |write_lock_| held. This object may be destroyed by this call. This - // acquires |read_lock_| inside of it. The caller needs to acquire read_lock_ + // acquires |write_lock_| inside of it. The caller needs to acquire read_lock_ // first. void OnReadCompletedNoLock(IOResult io_result, size_t bytes_read); // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT @@ -414,6 +416,9 @@ // Connects to the OS pipe. void LazyInitialize(); + // base::MessageLoop::DestructionObserver: + void WillDestroyCurrentMessageLoop() override; +
diff --git a/mojo/edk/system/raw_channel_posix.cc b/mojo/edk/system/raw_channel_posix.cc index e6627d6..93a97ed 100644 --- a/mojo/edk/system/raw_channel_posix.cc +++ b/mojo/edk/system/raw_channel_posix.cc
@@ -566,19 +566,25 @@ } bool RawChannel::IsOtherEndOf(RawChannel* other) { +#if defined(OFFICIAL_BUILD) + return false; +#else + // We don't check the return code of getsockopt because this is only available + // on Linux after 3.4. This is a developer error, so we just have to catch it + // on platforms that developers use. + // Note that since we're storing a 32 bit integer, we can get collisions so we + // will only use it in non-official builds. DCHECK_NE(other, this); PlatformHandle this_handle = static_cast<RawChannelPosix*>(this)->GetFD(); PlatformHandle other_handle = static_cast<RawChannelPosix*>(other)->GetFD(); - // We don't check the return code of getsockopt because this is only available - // on Linux after 3.4. This is a developer error, so we just have to catch it - // on platforms that developers use. int id1 = 0; int id2 = 1; socklen_t peek_off_size = sizeof(id1); getsockopt(this_handle.fd, SOL_SOCKET, SO_PEEK_OFF, &id1, &peek_off_size); getsockopt(other_handle.fd, SOL_SOCKET, SO_PEEK_OFF, &id2, &peek_off_size); return id1 == id2; +#endif } } // namespace edk
diff --git a/mojo/edk/system/raw_channel_win.cc b/mojo/edk/system/raw_channel_win.cc index 0ceb521..1e274555 100644 --- a/mojo/edk/system/raw_channel_win.cc +++ b/mojo/edk/system/raw_channel_win.cc
@@ -19,6 +19,7 @@ #include "base/win/windows_version.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/platform_handle.h" +#include "mojo/edk/system/token_serializer_win.h" #include "mojo/edk/system/transport_data.h" #include "mojo/public/cpp/system/macros.h" @@ -30,11 +31,6 @@ namespace { -struct MOJO_ALIGNAS(8) SerializedHandle { - DWORD handle_pid; - HANDLE handle; -}; - class VistaOrHigherFunctions { public: VistaOrHigherFunctions() @@ -602,35 +598,14 @@ ScopedPlatformHandleVectorPtr GetReadPlatformHandles( size_t num_platform_handles, const void* platform_handle_table) override { - // TODO(jam): this code will have to be updated once it's used in a sandbox - // and the receiving process doesn't have duplicate permission for the - // receiver. Once there's a broker and we have a connection to it (possibly - // through ConnectionManager), then we can make a sync IPC to it here to get - // a token for this handle, and it will duplicate the handle to is process. - // Then we pass the token to the receiver, which will then make a sync call - // to the broker to get a duplicated handle. This will also allow us to - // avoid leaks of the handle if the receiver dies, since the broker can - // notice that. DCHECK_GT(num_platform_handles, 0u); ScopedPlatformHandleVectorPtr rv(new PlatformHandleVector()); + rv->resize(num_platform_handles); - const SerializedHandle* serialization_data = - static_cast<const SerializedHandle*>(platform_handle_table); - for (size_t i = 0; i < num_platform_handles; i++) { - DWORD pid = serialization_data->handle_pid; - HANDLE source_handle = serialization_data->handle; - serialization_data ++; - base::Process sender = - base::Process::OpenWithAccess(pid, PROCESS_DUP_HANDLE); - DCHECK(sender.IsValid()); - HANDLE target_handle = NULL; - BOOL dup_result = DuplicateHandle( - sender.Handle(), source_handle, - base::GetCurrentProcessHandle(), &target_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); - DCHECK(dup_result); - rv->push_back(PlatformHandle(target_handle)); - } + const uint64_t* tokens = + static_cast<const uint64_t*>(platform_handle_table); + internal::g_token_serializer->TokenToHandle( + tokens, num_platform_handles, &rv->at(0)); return rv.Pass(); } @@ -638,26 +613,19 @@ if (!write_buffer_no_lock()->HavePlatformHandlesToSend()) return 0u; - // Since we're not sure which process might ultimately deserialize this - // message, we can't duplicate the handle now. Instead, write the process - // ID and handle now and let the receiver duplicate it. PlatformHandle* platform_handles; void* serialization_data_temp; size_t num_platform_handles; write_buffer_no_lock()->GetPlatformHandlesToSend( &num_platform_handles, &platform_handles, &serialization_data_temp); - SerializedHandle* serialization_data = - static_cast<SerializedHandle*>(serialization_data_temp); + uint64_t* tokens = static_cast<uint64_t*>(serialization_data_temp); DCHECK_GT(num_platform_handles, 0u); DCHECK(platform_handles); - DWORD current_process_id = base::GetCurrentProcId(); - for (size_t i = 0; i < num_platform_handles; i++) { - serialization_data->handle_pid = current_process_id; - serialization_data->handle = platform_handles[i].handle; - serialization_data++; + internal::g_token_serializer->HandleToToken( + &platform_handles[0], num_platform_handles, tokens); + for (size_t i = 0; i < num_platform_handles; i++) platform_handles[i] = PlatformHandle(); - } return num_platform_handles; } @@ -778,7 +746,7 @@ } size_t RawChannel::GetSerializedPlatformHandleSize() { - return sizeof(SerializedHandle); + return sizeof(uint64_t); } bool RawChannel::IsOtherEndOf(RawChannel* other) {
diff --git a/mojo/edk/system/simple_token_serializer_win.cc b/mojo/edk/system/simple_token_serializer_win.cc new file mode 100644 index 0000000..e318ad1 --- /dev/null +++ b/mojo/edk/system/simple_token_serializer_win.cc
@@ -0,0 +1,78 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/simple_token_serializer_win.h" + +#include <windows.h> + +#include "base/process/process.h" +#include "mojo/edk/embedder/platform_channel_pair.h" + +namespace mojo { +namespace edk { + +SimpleTokenSerializer::SimpleTokenSerializer() { +} + +SimpleTokenSerializer::~SimpleTokenSerializer() { +} + +void SimpleTokenSerializer::CreatePlatformChannelPair( + ScopedPlatformHandle* server, ScopedPlatformHandle* client) { + PlatformChannelPair channel_pair; + *server = channel_pair.PassServerHandle(); + *client = channel_pair.PassClientHandle(); +} + +void SimpleTokenSerializer::HandleToToken( + const PlatformHandle* platform_handles, + size_t count, + uint64_t* tokens) { + // Since we're not sure which process might ultimately deserialize the message + // we can't duplicate the handle now. Instead, write the process ID and handle + // now and let the receiver duplicate it. + uint32_t current_process_id = base::GetCurrentProcId(); + for (size_t i = 0; i < count; ++i) { + tokens[i] = current_process_id; + tokens[i] = tokens[i] << 32; + // Windows HANDLES are always 32 bit per + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203(v=vs.85).aspx +#if defined(_WIN64) + tokens[i] |= static_cast<int32_t>( + reinterpret_cast<int64_t>(platform_handles[i].handle)); +#else + tokens[i] |= reinterpret_cast<int32_t>(platform_handles[i].handle); +#endif + } +} + +void SimpleTokenSerializer::TokenToHandle(const uint64_t* tokens, + size_t count, + PlatformHandle* handles) { + for (size_t i = 0; i < count; ++i) { + DWORD pid = tokens[i] >> 32; +#if defined(_WIN64) + // Sign-extend to preserve INVALID_HANDLE_VALUE. + HANDLE source_handle = reinterpret_cast<HANDLE>( + static_cast<int64_t>(static_cast<int32_t>(tokens[i] & 0xFFFFFFFF))); +#else + HANDLE source_handle = reinterpret_cast<HANDLE>(tokens[i] & 0xFFFFFFFF); +#endif + base::Process sender = + base::Process::OpenWithAccess(pid, PROCESS_DUP_HANDLE); + handles[i] = PlatformHandle(); + if (!sender.IsValid()) { + // Sender died. + } else { + BOOL dup_result = DuplicateHandle( + sender.Handle(), source_handle, + base::GetCurrentProcessHandle(), &handles[i].handle, 0, + FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); + DCHECK(dup_result); + } + } +} + +} // namespace edk +} // namespace mojo
diff --git a/mojo/edk/system/simple_token_serializer_win.h b/mojo/edk/system/simple_token_serializer_win.h new file mode 100644 index 0000000..8e910f8 --- /dev/null +++ b/mojo/edk/system/simple_token_serializer_win.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 MOJO_EDK_SYSTEM_SIMPLE_TOKEN_SERIALIZER_WIN_H_ +#define MOJO_EDK_SYSTEM_SIMPLE_TOKEN_SERIALIZER_WIN_H_ + +#include "mojo/edk/system/token_serializer_win.h" + +namespace mojo { +namespace edk { + +// A simple implementation of TokenSerializer interface. This isn't meant for +// production use (i.e. with multi-process, sandboxes). It's provided for use by +// unittests. +// Implementation note: this default implementation works across processes +// without a sandbox. +class MOJO_SYSTEM_IMPL_EXPORT SimpleTokenSerializer : public TokenSerializer { + public: + SimpleTokenSerializer(); + ~SimpleTokenSerializer() override; + + // TokenSerializer implementation: + void CreatePlatformChannelPair(ScopedPlatformHandle* server, + ScopedPlatformHandle* client) override; + void HandleToToken(const PlatformHandle* platform_handles, + size_t count, + uint64_t* tokens) override; + void TokenToHandle(const uint64_t* tokens, + size_t count, + PlatformHandle* handles) override; +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_SIMPLE_TOKEN_SERIALIZER_WIN_H_
diff --git a/mojo/edk/system/token_serializer_messages_win.h b/mojo/edk/system/token_serializer_messages_win.h new file mode 100644 index 0000000..3de4bf4 --- /dev/null +++ b/mojo/edk/system/token_serializer_messages_win.h
@@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_TOKEN_SERIALIZER_MESSAGES_WIN_H_ +#define MOJO_EDK_SYSTEM_TOKEN_SERIALIZER_MESSAGES_WIN_H_ + +#include <stdint.h> + +#include "base/compiler_specific.h" + +namespace mojo { +namespace edk { + +// This header defines the message format between ChildTokenSerializer and +// ParentTokenSerializer. + +enum MessageId { + // The reply is two HANDLEs. + CREATE_PLATFORM_CHANNEL_PAIR = 0, + // The reply is tokens of the same count of passed in handles. + HANDLE_TO_TOKEN, + // The reply is handles of the same count of passed in tokens. + TOKEN_TO_HANDLE, +}; + +// Definitions of the raw bytes sent between ChildTokenSerializer and +// ParentTokenSerializer. + +struct ALIGNAS(4) TokenSerializerMessage { + uint32_t size; + MessageId id; + // Data, if any, follows. + union { + HANDLE handles[1]; // If HANDLE_TO_TOKEN. + uint64_t tokens[1]; // If TOKEN_TO_HANDLE. + }; +}; + +const int kTokenSerializerMessageHeaderSize = + sizeof(uint32_t) + sizeof(MessageId); + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_TOKEN_SERIALIZER_MESSAGES_WIN_H_
diff --git a/mojo/edk/system/token_serializer_win.h b/mojo/edk/system/token_serializer_win.h new file mode 100644 index 0000000..7b94bc9 --- /dev/null +++ b/mojo/edk/system/token_serializer_win.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 MOJO_EDK_SYSTEM_TOKEN_SERIALIZER_WIN_H_ +#define MOJO_EDK_SYSTEM_TOKEN_SERIALIZER_WIN_H_ + +#include <stdint.h> +#include <vector> + +#include "mojo/edk/embedder/scoped_platform_handle.h" + +namespace mojo { +namespace edk { + +// An interface for serializing a Mojo handle to memory. A child process will +// have to make sync calls to the parent process. It is safe to call from any +// thread. +class MOJO_SYSTEM_IMPL_EXPORT TokenSerializer { + public: + virtual ~TokenSerializer() {} + + // Create a PlatformChannelPair. + virtual void CreatePlatformChannelPair(ScopedPlatformHandle* server, + ScopedPlatformHandle* client) = 0; + + // Converts the given platform handles to tokens. + // |tokens| should point to memory that is sizeof(uint64_t) * count; + virtual void HandleToToken(const PlatformHandle* platform_handles, + size_t count, + uint64_t* tokens) = 0; + + // Converts the given tokens to platformhandles. + // |handles| should point to memory that is sizeof(HANDLE) * count; + virtual void TokenToHandle(const uint64_t* tokens, + size_t count, + PlatformHandle* handles) = 0; +}; + +} // namespace edk +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_TOKEN_SERIALIZER_WIN_H_
diff --git a/mojo/edk/system/transport_data.cc b/mojo/edk/system/transport_data.cc index 4f92f95..92567f15 100644 --- a/mojo/edk/system/transport_data.cc +++ b/mojo/edk/system/transport_data.cc
@@ -18,7 +18,7 @@ // |TransportData::kMaxBufferSize|. This value should be a multiple of the // alignment in order to simplify calculations, even though the actual amount of // space needed need not be a multiple of the alignment. -const size_t kMaxSizePerPlatformHandle = 16; +const size_t kMaxSizePerPlatformHandle = 8; static_assert(kMaxSizePerPlatformHandle % MessageInTransit::kMessageAlignment == 0, "kMaxSizePerPlatformHandle not a multiple of alignment");
diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc index c6990b26..e219123 100644 --- a/mojo/gles2/command_buffer_client_impl.cc +++ b/mojo/gles2/command_buffer_client_impl.cc
@@ -56,12 +56,14 @@ : initialized_successfully_(false), binding_(this, ptr, async_waiter) {} bool WaitForInitialization() { + base::ThreadRestrictions::ScopedAllowWait wait; if (!binding_.WaitForIncomingMethodCall()) return false; return initialized_successfully_; } mus::mojom::CommandBufferStatePtr WaitForProgress() { + base::ThreadRestrictions::ScopedAllowWait wait; if (!binding_.WaitForIncomingMethodCall()) return mus::mojom::CommandBufferStatePtr(); return command_buffer_state_.Pass(); @@ -100,6 +102,7 @@ : sync_point_(0u), binding_(this, ptr, async_waiter) {} uint32_t WaitForInsertSyncPoint() { + base::ThreadRestrictions::ScopedAllowWait wait; if (!binding_.WaitForIncomingMethodCall()) return 0u; uint32_t result = sync_point_; @@ -142,8 +145,6 @@ CommandBufferClientImpl::~CommandBufferClientImpl() {} bool CommandBufferClientImpl::Initialize() { - base::ThreadRestrictions::ScopedAllowWait wait; - const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState); void* memory = NULL; mojo::ScopedSharedBufferHandle duped; @@ -332,7 +333,6 @@ } uint32_t CommandBufferClientImpl::InsertSyncPoint() { - base::ThreadRestrictions::ScopedAllowWait wait; command_buffer_->InsertSyncPoint(true); return sync_point_client_impl_->WaitForInsertSyncPoint(); }
diff --git a/mojo/message_pump/handle_watcher.cc b/mojo/message_pump/handle_watcher.cc index a8d007a..b2320cc5 100644 --- a/mojo/message_pump/handle_watcher.cc +++ b/mojo/message_pump/handle_watcher.cc
@@ -223,13 +223,7 @@ } WatcherThreadManager* WatcherThreadManager::GetInstance() { - // We need to leak this because otherwise when the process dies, AtExitManager - // waits for destruction which waits till the handle watcher thread is joined. - // But that can't happen since the pump uses mojo message pipes to wake up the - // pump. Since mojo EDK has been shutdown already, this never completes. - return base::Singleton<WatcherThreadManager, - base::LeakySingletonTraits<WatcherThreadManager>>:: - get(); + return base::Singleton<WatcherThreadManager>::get(); } WatcherID WatcherThreadManager::StartWatching(
diff --git a/mojo/message_pump/message_pump_mojo.cc b/mojo/message_pump/message_pump_mojo.cc index 248c33a4..cd22017 100644 --- a/mojo/message_pump/message_pump_mojo.cc +++ b/mojo/message_pump/message_pump_mojo.cc
@@ -90,10 +90,15 @@ handler_data.deadline = deadline; handler_data.id = next_handler_id_++; handlers_[handle] = handler_data; + if (!deadline.is_null()) { + bool inserted = deadline_handles_.insert(handle).second; + DCHECK(inserted); + } } void MessagePumpMojo::RemoveHandler(const Handle& handle) { handlers_.erase(handle); + deadline_handles_.erase(handle); } void MessagePumpMojo::AddObserver(Observer* observer) { @@ -168,15 +173,23 @@ const MojoDeadline deadline = block ? GetDeadlineForWait(run_state) : 0; const WaitState wait_state = GetWaitState(); + std::vector<MojoHandleSignalsState> states(wait_state.handles.size()); const WaitManyResult wait_many_result = - WaitMany(wait_state.handles, wait_state.wait_signals, deadline, nullptr); + WaitMany(wait_state.handles, wait_state.wait_signals, deadline, &states); const MojoResult result = wait_many_result.result; bool did_work = true; if (result == MOJO_RESULT_OK) { if (wait_many_result.index == 0) { - // Control pipe was written to. - ReadMessageRaw(read_handle_.get(), NULL, NULL, NULL, NULL, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); + if (states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_CLOSED) { + // The Mojo EDK is shutting down. The ThreadQuitHelper task in + // base::Thread won't get run since the control pipe depends on the EDK + // staying alive. So quit manually to avoid this thread hanging. + Quit(); + } else { + // Control pipe was written to. + ReadMessageRaw(read_handle_.get(), NULL, NULL, NULL, NULL, + MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); + } } else { DCHECK(handlers_.find(wait_state.handles[wait_many_result.index]) != handlers_.end()); @@ -201,21 +214,31 @@ } } - // Notify and remove any handlers whose time has expired. Make a copy in case - // someone tries to add/remove new handlers from notification. - const HandleToHandler cloned_handlers(handlers_); + // Notify and remove any handlers whose time has expired. First, iterate over + // the set of handles that have a deadline, and add the expired handles to a + // map of <Handle, id>. Then, iterate over those expired handles and remove + // them. The two-step process is because a handler can add/remove new + // handlers. + std::map<Handle, int> expired_handles; const base::TimeTicks now(internal::NowTicks()); - for (HandleToHandler::const_iterator i = cloned_handlers.begin(); - i != cloned_handlers.end(); ++i) { - // Since we're iterating over a clone of the handlers, verify the handler is - // still valid before notifying. - if (!i->second.deadline.is_null() && i->second.deadline < now && - handlers_.find(i->first) != handlers_.end() && - handlers_[i->first].id == i->second.id) { + for (const Handle handle : deadline_handles_) { + const auto it = handlers_.find(handle); + // Expect any handle in |deadline_handles_| to also be in |handlers_| since + // the two are modified in lock-step. + DCHECK(it != handlers_.end()); + if (!it->second.deadline.is_null() && it->second.deadline < now) + expired_handles[handle] = it->second.id; + } + for (auto& pair : expired_handles) { + auto it = handlers_.find(pair.first); + // Don't need to check deadline again since it can't change if id hasn't + // changed. + if (it != handlers_.end() && it->second.id == pair.second) { + MessagePumpMojoHandler* handler = handlers_[pair.first].handler; + RemoveHandler(pair.first); WillSignalHandler(); - i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED); + handler->OnHandleError(pair.first, MOJO_RESULT_DEADLINE_EXCEEDED); DidSignalHandler(); - handlers_.erase(i->first); did_work = true; } } @@ -232,12 +255,12 @@ // Remove the handle first, this way if OnHandleError() tries to remove the // handle our iterator isn't invalidated. - CHECK(handlers_.find(wait_state.handles[index]) != handlers_.end()); - MessagePumpMojoHandler* handler = - handlers_[wait_state.handles[index]].handler; - handlers_.erase(wait_state.handles[index]); + Handle handle = wait_state.handles[index]; + CHECK(handlers_.find(handle) != handlers_.end()); + MessagePumpMojoHandler* handler = handlers_[handle].handler; + RemoveHandler(handle); WillSignalHandler(); - handler->OnHandleError(wait_state.handles[index], result); + handler->OnHandleError(handle, result); DidSignalHandler(); } @@ -245,6 +268,11 @@ const MojoResult result = WriteMessageRaw(write_handle_.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); + if (result == MOJO_RESULT_FAILED_PRECONDITION) { + // Mojo EDK is shutting down. + return; + } + // If we can't write we likely won't wake up the thread and there is a strong // chance we'll deadlock. CHECK_EQ(MOJO_RESULT_OK, result); @@ -253,7 +281,8 @@ MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState() const { WaitState wait_state; wait_state.handles.push_back(read_handle_.get()); - wait_state.wait_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); + wait_state.wait_signals.push_back( + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED); for (HandleToHandler::const_iterator i = handlers_.begin(); i != handlers_.end(); ++i) { @@ -268,10 +297,11 @@ const base::TimeTicks now(internal::NowTicks()); MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, now); - for (HandleToHandler::const_iterator i = handlers_.begin(); - i != handlers_.end(); ++i) { + for (const Handle handle : deadline_handles_) { + auto it = handlers_.find(handle); + DCHECK(it != handlers_.end()); deadline = std::min( - TimeTicksToMojoDeadline(i->second.deadline, now), deadline); + TimeTicksToMojoDeadline(it->second.deadline, now), deadline); } return deadline; }
diff --git a/mojo/message_pump/message_pump_mojo.h b/mojo/message_pump/message_pump_mojo.h index 5e7eb6c..4dc0c223 100644 --- a/mojo/message_pump/message_pump_mojo.h +++ b/mojo/message_pump/message_pump_mojo.h
@@ -6,6 +6,7 @@ #define MOJO_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_H_ #include <map> +#include <set> #include "base/macros.h" #include "base/memory/scoped_ptr.h" @@ -117,6 +118,10 @@ base::Lock run_state_lock_; HandleToHandler handlers_; + // Set of handles that have a deadline set. Avoids iterating over all elements + // in |handles_| in the common case (no deadline set). + // TODO(amistry): Make this better and avoid special-casing deadlines. + std::set<Handle> deadline_handles_; // An ever increasing value assigned to each Handler::id. Used to detect // uniqueness while notifying. That is, while notifying expired timers we copy
diff --git a/mojo/mojo_base.gyp b/mojo/mojo_base.gyp index 759bbca..2eb3651 100644 --- a/mojo/mojo_base.gyp +++ b/mojo/mojo_base.gyp
@@ -205,6 +205,7 @@ 'variables': { 'mojom_files': [ 'application/public/interfaces/application.mojom', + 'application/public/interfaces/application_manager.mojom', 'application/public/interfaces/content_handler.mojom', 'application/public/interfaces/service_provider.mojom', 'application/public/interfaces/shell.mojom',
diff --git a/mojo/mojo_edk.gyp b/mojo/mojo_edk.gyp index 531def5..a60e2c75 100644 --- a/mojo/mojo_edk.gyp +++ b/mojo/mojo_edk.gyp
@@ -67,6 +67,8 @@ 'edk/system/awakable_list.h', 'edk/system/async_waiter.cc', 'edk/system/async_waiter.h', + 'edk/system/child_token_serializer_win.cc', + 'edk/system/child_token_serializer_win.h', 'edk/system/configuration.cc', 'edk/system/configuration.h', 'edk/system/core.cc', @@ -91,6 +93,10 @@ 'edk/system/message_pipe_dispatcher.cc', 'edk/system/message_pipe_dispatcher.h', 'edk/system/options_validation.h', + 'edk/system/parent_token_serializer_state_win.cc', + 'edk/system/parent_token_serializer_state_win.h', + 'edk/system/parent_token_serializer_win.cc', + 'edk/system/parent_token_serializer_win.h', 'edk/system/platform_handle_dispatcher.cc', 'edk/system/platform_handle_dispatcher.h', 'edk/system/raw_channel.cc', @@ -101,6 +107,10 @@ 'edk/system/shared_buffer_dispatcher.h', 'edk/system/simple_dispatcher.cc', 'edk/system/simple_dispatcher.h', + 'edk/system/simple_token_serializer_win.cc', + 'edk/system/simple_token_serializer_win.h', + 'edk/system/token_serializer_messages_win.h', + 'edk/system/token_serializer_win.h', 'edk/system/transport_data.cc', 'edk/system/transport_data.h', 'edk/system/waiter.cc',
diff --git a/mojo/mojo_shell.gyp b/mojo/mojo_shell.gyp index a4290af7..65c80301 100644 --- a/mojo/mojo_shell.gyp +++ b/mojo/mojo_shell.gyp
@@ -47,7 +47,6 @@ '<(DEPTH)/mojo/mojo_base.gyp:mojo_common_lib', '<(DEPTH)/mojo/mojo_base.gyp:mojo_environment_chromium', '<(DEPTH)/mojo/mojo_base.gyp:mojo_url_type_converters', - '<(DEPTH)/mojo/mojo_shell.gyp:mojo_shell_interfaces', '<(DEPTH)/url/url.gyp:url_lib', ], }, { @@ -123,16 +122,5 @@ 'includes': [ '../third_party/mojo/mojom_bindings_generator_explicit.gypi', ], - }, { - 'target_name': 'mojo_shell_interfaces', - 'type': 'none', - 'variables': { - 'mojom_files': [ - 'shell/application_manager.mojom', - ], - }, - 'includes': [ - '../third_party/mojo/mojom_bindings_generator_explicit.gypi', - ], }], }
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index 60874fe..52778fb 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -5,6 +5,9 @@ source_set("bindings") { sources = [ "array.h", + "associated_binding.h", + "associated_group.h", + "associated_interface_ptr.h", "associated_interface_ptr_info.h", "associated_interface_request.h", "binding.h", @@ -14,6 +17,8 @@ "lib/array_internal.cc", "lib/array_internal.h", "lib/array_serialization.h", + "lib/associated_group.cc", + "lib/associated_interface_ptr_internal.h", "lib/bindings_internal.h", "lib/bindings_serialization.cc", "lib/bindings_serialization.h",
diff --git a/mojo/public/cpp/bindings/associated_binding.h b/mojo/public/cpp/bindings/associated_binding.h new file mode 100644 index 0000000..bd6b203b --- /dev/null +++ b/mojo/public/cpp/bindings/associated_binding.h
@@ -0,0 +1,138 @@ +// Copyright 2015 The Chromium Authors. 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_ASSOCIATED_BINDING_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/public/cpp/bindings/associated_group.h" +#include "mojo/public/cpp/bindings/associated_interface_request.h" +#include "mojo/public/cpp/bindings/callback.h" +#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" + +namespace mojo { + +// Represents the implementation side of an associated interface. It is similar +// to Binding, except that it doesn't own a message pipe handle. +template <typename Interface> +class AssociatedBinding { + public: + // Constructs an incomplete associated binding that will use the + // implementation |impl|. It may be completed with a subsequent call to the + // |Bind| method. Does not take ownership of |impl|, which must outlive this + // object. + explicit AssociatedBinding(Interface* impl) : impl_(impl) { + stub_.set_sink(impl_); + } + + // Constructs a completed associated binding of |impl|. The output |ptr_info| + // should be passed through the message pipe endpoint referred to by + // |associated_group| to setup the corresponding asssociated interface + // pointer. |impl| must outlive this object. + AssociatedBinding(Interface* impl, + AssociatedInterfacePtrInfo<Interface>* ptr_info, + AssociatedGroup* associated_group) + : AssociatedBinding(impl) { + Bind(ptr_info, associated_group); + } + + // Constructs a completed associated binding of |impl|. |impl| must outlive + // the binding. + AssociatedBinding(Interface* impl, + AssociatedInterfaceRequest<Interface> request) + : AssociatedBinding(impl) { + Bind(request.Pass()); + } + + ~AssociatedBinding() {} + + // Creates an associated inteface and sets up this object as the + // implementation side. The output |ptr_info| should be passed through the + // message pipe endpoint referred to by |associated_group| to setup the + // corresponding asssociated interface pointer. + void Bind(AssociatedInterfacePtrInfo<Interface>* ptr_info, + AssociatedGroup* associated_group) { + AssociatedInterfaceRequest<Interface> request; + associated_group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_PTR, + ptr_info, &request); + Bind(request.Pass()); + } + + // Sets up this object as the implementation side of an associated interface. + void Bind(AssociatedInterfaceRequest<Interface> request) { + internal::ScopedInterfaceEndpointHandle handle = + internal::AssociatedInterfaceRequestHelper::PassHandle(&request); + + DCHECK(handle.is_local()) + << "The AssociatedInterfaceRequest is supposed to be used at the " + << "other side of the message pipe."; + + if (!handle.is_valid() || !handle.is_local()) { + endpoint_client_.reset(); + return; + } + + endpoint_client_.reset(new internal::InterfaceEndpointClient( + handle.Pass(), &stub_, + make_scoped_ptr(new typename Interface::RequestValidator_()))); + + endpoint_client_->set_connection_error_handler( + [this]() { connection_error_handler_.Run(); }); + } + + // Closes the associated interface. Puts this object into a state where it can + // be rebound. + void Close() { + DCHECK(endpoint_client_); + endpoint_client_.reset(); + } + + // Unbinds and returns the associated interface request so it can be + // used in another context, such as on another thread or with a different + // implementation. Puts this object into a state where it can be rebound. + AssociatedInterfaceRequest<Interface> Unbind() { + DCHECK(endpoint_client_); + + AssociatedInterfaceRequest<Interface> request; + internal::AssociatedInterfaceRequestHelper::SetHandle( + &request, endpoint_client_->PassHandle()); + + endpoint_client_.reset(); + + return request.Pass(); + } + + // Sets an error handler that will be called if a connection error occurs. + void set_connection_error_handler(const Closure& error_handler) { + connection_error_handler_ = error_handler; + } + + // Returns the interface implementation that was previously specified. + Interface* impl() { return impl_; } + + // Indicates whether the associated binding has been completed. + bool is_bound() const { return !!endpoint_client_; } + + // Returns the associated group that this object belongs to. Returns null if + // the object is not bound. + AssociatedGroup* associated_group() { + return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; + } + + private: + scoped_ptr<internal::InterfaceEndpointClient> endpoint_client_; + + typename Interface::Stub_ stub_; + Interface* impl_; + Closure connection_error_handler_; + + DISALLOW_COPY_AND_ASSIGN(AssociatedBinding); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
diff --git a/mojo/public/cpp/bindings/associated_group.h b/mojo/public/cpp/bindings/associated_group.h new file mode 100644 index 0000000..b6934e0 --- /dev/null +++ b/mojo/public/cpp/bindings/associated_group.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 MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ + +#include "base/memory/ref_counted.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" +#include "mojo/public/cpp/bindings/associated_interface_request.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" + +namespace mojo { + +namespace internal { +class MultiplexRouter; +} + +// AssociatedGroup refers to all the interface endpoints running at one end of a +// message pipe. It is used to create associated interfaces for that message +// pipe. +// It is thread safe and cheap to make copies. +class AssociatedGroup { + public: + // Configuration used by CreateAssociatedInterface(). Please see the comments + // of that method for more details. + enum AssociatedInterfaceConfig { WILL_PASS_PTR, WILL_PASS_REQUEST }; + + AssociatedGroup(); + AssociatedGroup(const AssociatedGroup& other); + + ~AssociatedGroup(); + + AssociatedGroup& operator=(const AssociatedGroup& other); + + // |config| indicates whether |ptr_info| or |request| will be sent to the + // remote side of the message pipe. + // + // NOTE: If |config| is |WILL_PASS_REQUEST|, you will want to bind |ptr_info| + // to a local AssociatedInterfacePtr to make calls. However, there is one + // restriction: the pointer should NOT be used to make calls before |request| + // is sent. Violating that will cause the message pipe to be closed. On the + // other hand, as soon as |request| is sent, the pointer is usable. There is + // no need to wait until |request| is bound to an implementation at the remote + // side. + template <typename T> + void CreateAssociatedInterface(AssociatedInterfaceConfig config, + AssociatedInterfacePtrInfo<T>* ptr_info, + AssociatedInterfaceRequest<T>* request) { + internal::ScopedInterfaceEndpointHandle local; + internal::ScopedInterfaceEndpointHandle remote; + CreateEndpointHandlePair(&local, &remote); + + if (!local.is_valid() || !remote.is_valid()) { + *ptr_info = AssociatedInterfacePtrInfo<T>(); + *request = AssociatedInterfaceRequest<T>(); + return; + } + + if (config == WILL_PASS_PTR) { + internal::AssociatedInterfacePtrInfoHelper::SetHandle(ptr_info, + remote.Pass()); + // The implementation is local, therefore set the version according to + // the interface definition that this code is built against. + ptr_info->set_version(T::Version_); + internal::AssociatedInterfaceRequestHelper::SetHandle(request, + local.Pass()); + } else { + internal::AssociatedInterfacePtrInfoHelper::SetHandle(ptr_info, + local.Pass()); + // The implementation is remote, we don't know about its actual version + // yet. + ptr_info->set_version(0u); + internal::AssociatedInterfaceRequestHelper::SetHandle(request, + remote.Pass()); + } + } + + private: + friend class internal::MultiplexRouter; + + void CreateEndpointHandlePair( + internal::ScopedInterfaceEndpointHandle* local_endpoint, + internal::ScopedInterfaceEndpointHandle* remote_endpoint); + + scoped_refptr<internal::MultiplexRouter> router_; +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_
diff --git a/mojo/public/cpp/bindings/associated_interface_ptr.h b/mojo/public/cpp/bindings/associated_interface_ptr.h new file mode 100644 index 0000000..9ae6128 --- /dev/null +++ b/mojo/public/cpp/bindings/associated_interface_ptr.h
@@ -0,0 +1,191 @@ +// Copyright 2015 The Chromium Authors. 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_ASSOCIATED_INTERFACE_PTR_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ + +#include <algorithm> + +#include "base/macros.h" +#include "mojo/public/cpp/bindings/associated_group.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" +#include "mojo/public/cpp/bindings/associated_interface_request.h" +#include "mojo/public/cpp/bindings/callback.h" +#include "mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h" + +namespace mojo { + +// Represents the client side of an associated interface. It is similar to +// InterfacePtr, except that it doesn't own a message pipe handle. +template <typename Interface> +class AssociatedInterfacePtr { + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfacePtr) + + public: + // Constructs an unbound AssociatedInterfacePtr. + AssociatedInterfacePtr() {} + AssociatedInterfacePtr(decltype(nullptr)) {} + + AssociatedInterfacePtr(AssociatedInterfacePtr&& other) { + internal_state_.Swap(&other.internal_state_); + } + + AssociatedInterfacePtr& operator=(AssociatedInterfacePtr&& other) { + reset(); + internal_state_.Swap(&other.internal_state_); + return *this; + } + + // Assigning nullptr to this class causes it to closes the associated + // interface (if any) and returns the pointer to the unbound state. + AssociatedInterfacePtr& operator=(decltype(nullptr)) { + reset(); + return *this; + } + + ~AssociatedInterfacePtr() {} + + // Sets up this object as the client side of an associated interface. + // Calling with an invalid |info| has the same effect as reset(). In this + // case, the AssociatedInterfacePtr is not considered as bound. + // + // NOTE: Please see the comments of + // AssociatedGroup.CreateAssociatedInterface() about when you can use this + // object to make calls. + void Bind(AssociatedInterfacePtrInfo<Interface> info) { + reset(); + + bool is_local = + internal::AssociatedInterfacePtrInfoHelper::GetHandle(&info).is_local(); + + DCHECK(is_local) << "The AssociatedInterfacePtrInfo is supposed to be used " + "at the other side of the message pipe."; + + if (info.is_valid() && is_local) + internal_state_.Bind(info.Pass()); + } + + bool is_bound() const { return internal_state_.is_bound(); } + + Interface* get() const { return internal_state_.instance(); } + + // Functions like a pointer to Interface. Must already be bound. + Interface* operator->() const { return get(); } + Interface& operator*() const { return *get(); } + + // Returns the version number of the interface that the remote side supports. + uint32_t version() const { return internal_state_.version(); } + + // Queries the max version that the remote side supports. On completion, the + // result will be returned as the input of |callback|. The version number of + // this object will also be updated. + void QueryVersion(const Callback<void(uint32_t)>& callback) { + internal_state_.QueryVersion(callback); + } + + // If the remote side doesn't support the specified version, it will close the + // associated interface asynchronously. This does nothing if it's already + // known that the remote side supports the specified version, i.e., if + // |version <= this->version()|. + // + // After calling RequireVersion() with a version not supported by the remote + // side, all subsequent calls to interface methods will be ignored. + void RequireVersion(uint32_t version) { + internal_state_.RequireVersion(version); + } + + // Closes the associated interface (if any) and returns the pointer to the + // unbound state. + void reset() { + State doomed; + internal_state_.Swap(&doomed); + } + + // Indicates whether an error has been encountered. If true, method calls made + // on this interface will be dropped (and may already have been dropped). + bool encountered_error() const { return internal_state_.encountered_error(); } + + // Registers a handler to receive error notifications. + // + // This method may only be called after the AssociatedInterfacePtr has been + // bound. + void set_connection_error_handler(const Closure& error_handler) { + internal_state_.set_connection_error_handler(error_handler); + } + + // Unbinds and returns the associated interface pointer information which + // could be used to setup an AssociatedInterfacePtr again. This method may be + // used to move the proxy to a different thread. + // + // It is an error to call PassInterface() while there are pending responses. + // TODO: fix this restriction, it's not always obvious when there is a + // pending response. + AssociatedInterfacePtrInfo<Interface> PassInterface() { + DCHECK(!internal_state_.has_pending_callbacks()); + State state; + internal_state_.Swap(&state); + + return state.PassInterface(); + } + + // Returns the associated group that this object belongs to. Returns null if + // the object is not bound. + AssociatedGroup* associated_group() { + return internal_state_->associated_group(); + } + + // DO NOT USE. Exposed only for internal use and for testing. + internal::AssociatedInterfacePtrState<Interface>* internal_state() { + return &internal_state_; + } + + // Allow AssociatedInterfacePtr<> to be used in boolean expressions, but not + // implicitly convertible to a real bool (which is dangerous). + private: + typedef internal::AssociatedInterfacePtrState<Interface> + AssociatedInterfacePtr::*Testable; + + public: + operator Testable() const { + return internal_state_.is_bound() ? &AssociatedInterfacePtr::internal_state_ + : nullptr; + } + + private: + // Forbid the == and != operators explicitly, otherwise AssociatedInterfacePtr + // will be converted to Testable to do == or != comparison. + template <typename T> + bool operator==(const AssociatedInterfacePtr<T>& other) const = delete; + template <typename T> + bool operator!=(const AssociatedInterfacePtr<T>& other) const = delete; + + typedef internal::AssociatedInterfacePtrState<Interface> State; + mutable State internal_state_; +}; + +// Creates an associated interface. The output |ptr| should be used locally +// while the returned request should be passed through the message pipe endpoint +// referred to by |associated_group| to setup the corresponding asssociated +// interface implementation at the remote side. +// +// NOTE: |ptr| should NOT be used to make calls before the request is sent. +// Violating that will cause the message pipe to be closed. On the other hand, +// as soon as the request is sent, |ptr| is usable. There is no need to wait +// until the request is bound to an implementation at the remote side. +template <typename Interface> +AssociatedInterfaceRequest<Interface> GetProxy( + AssociatedInterfacePtr<Interface>* ptr, + AssociatedGroup* group) { + AssociatedInterfaceRequest<Interface> request; + AssociatedInterfacePtrInfo<Interface> ptr_info; + group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_REQUEST, + &ptr_info, &request); + + ptr->Bind(ptr_info.Pass()); + return request.Pass(); +} + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_
diff --git a/mojo/public/cpp/bindings/associated_interface_ptr_info.h b/mojo/public/cpp/bindings/associated_interface_ptr_info.h index 55f9c4a..43f9027 100644 --- a/mojo/public/cpp/bindings/associated_interface_ptr_info.h +++ b/mojo/public/cpp/bindings/associated_interface_ptr_info.h
@@ -5,28 +5,81 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ -#include "mojo/public/cpp/system/macros.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" namespace mojo { +namespace internal { +class AssociatedInterfacePtrInfoHelper; +} + // AssociatedInterfacePtrInfo stores necessary information to construct an -// associated interface pointer. -// TODO(yzshen): implement it. +// associated interface pointer. It is similar to InterfacePtrInfo except that +// it doesn't own a message pipe handle. template <typename Interface> class AssociatedInterfacePtrInfo { - MOJO_MOVE_ONLY_TYPE(AssociatedInterfacePtrInfo); + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfacePtrInfo); public: - AssociatedInterfacePtrInfo() {} - AssociatedInterfacePtrInfo(AssociatedInterfacePtrInfo&& other) {} + AssociatedInterfacePtrInfo() : version_(0u) {} + + AssociatedInterfacePtrInfo(AssociatedInterfacePtrInfo&& other) + : handle_(other.handle_.Pass()), version_(other.version_) { + other.version_ = 0u; + } + + ~AssociatedInterfacePtrInfo() {} AssociatedInterfacePtrInfo& operator=(AssociatedInterfacePtrInfo&& other) { + if (this != &other) { + handle_ = other.handle_.Pass(); + version_ = other.version_; + other.version_ = 0u; + } + return *this; } - bool is_valid() const { return false; } + bool is_valid() const { return handle_.is_valid(); } + + uint32_t version() const { return version_; } + void set_version(uint32_t version) { version_ = version; } + + private: + friend class internal::AssociatedInterfacePtrInfoHelper; + + internal::ScopedInterfaceEndpointHandle handle_; + uint32_t version_; }; +namespace internal { + +// With this helper, AssociatedInterfacePtrInfo doesn't have to expose any +// operations related to ScopedInterfaceEndpointHandle, which is an internal +// class. +class AssociatedInterfacePtrInfoHelper { + public: + template <typename Interface> + static ScopedInterfaceEndpointHandle PassHandle( + AssociatedInterfacePtrInfo<Interface>* info) { + return info->handle_.Pass(); + } + + template <typename Interface> + static const ScopedInterfaceEndpointHandle& GetHandle( + AssociatedInterfacePtrInfo<Interface>* info) { + return info->handle_; + } + + template <typename Interface> + static void SetHandle(AssociatedInterfacePtrInfo<Interface>* info, + ScopedInterfaceEndpointHandle handle) { + info->handle_ = handle.Pass(); + } +}; + +} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_
diff --git a/mojo/public/cpp/bindings/associated_interface_request.h b/mojo/public/cpp/bindings/associated_interface_request.h index 9882b890..96019a39 100644 --- a/mojo/public/cpp/bindings/associated_interface_request.h +++ b/mojo/public/cpp/bindings/associated_interface_request.h
@@ -5,27 +5,83 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ -#include "mojo/public/cpp/system/macros.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" namespace mojo { -// Represents an associated interface request. -// TODO(yzshen): implement it. +namespace internal { +class AssociatedInterfaceRequestHelper; +} + +// AssociatedInterfaceRequest represents an associated interface request. It is +// similar to InterfaceRequest except that it doesn't own a message pipe handle. template <typename Interface> class AssociatedInterfaceRequest { - MOJO_MOVE_ONLY_TYPE(AssociatedInterfaceRequest) + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfaceRequest); public: + // Constructs an empty AssociatedInterfaceRequest, representing that the + // client is not requesting an implementation of Interface. AssociatedInterfaceRequest() {} - AssociatedInterfaceRequest(AssociatedInterfaceRequest&& other) {} + AssociatedInterfaceRequest(decltype(nullptr)) {} + // Takes the interface endpoint handle from another + // AssociatedInterfaceRequest. + AssociatedInterfaceRequest(AssociatedInterfaceRequest&& other) { + handle_ = other.handle_.Pass(); + } AssociatedInterfaceRequest& operator=(AssociatedInterfaceRequest&& other) { + if (this != &other) + handle_ = other.handle_.Pass(); return *this; } - bool is_pending() const { return false; } + // Assigning to nullptr resets the AssociatedInterfaceRequest to an empty + // state, closing the interface endpoint handle currently bound to it (if + // any). + AssociatedInterfaceRequest& operator=(decltype(nullptr)) { + handle_.reset(); + return *this; + } + + // Indicates whether the request currently contains a valid interface endpoint + // handle. + bool is_pending() const { return handle_.is_valid(); } + + private: + friend class internal::AssociatedInterfaceRequestHelper; + + internal::ScopedInterfaceEndpointHandle handle_; }; +namespace internal { + +// With this helper, AssociatedInterfaceRequest doesn't have to expose any +// operations related to ScopedInterfaceEndpointHandle, which is an internal +// class. +class AssociatedInterfaceRequestHelper { + public: + template <typename Interface> + static ScopedInterfaceEndpointHandle PassHandle( + AssociatedInterfaceRequest<Interface>* request) { + return request->handle_.Pass(); + } + + template <typename Interface> + static const ScopedInterfaceEndpointHandle& GetHandle( + AssociatedInterfaceRequest<Interface>* request) { + return request->handle_; + } + + template <typename Interface> + static void SetHandle(AssociatedInterfaceRequest<Interface>* request, + ScopedInterfaceEndpointHandle handle) { + request->handle_ = handle.Pass(); + } +}; + +} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_
diff --git a/mojo/public/cpp/bindings/lib/associated_group.cc b/mojo/public/cpp/bindings/lib/associated_group.cc new file mode 100644 index 0000000..0bdf809d --- /dev/null +++ b/mojo/public/cpp/bindings/lib/associated_group.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/public/cpp/bindings/associated_group.h" + +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" + +namespace mojo { + +AssociatedGroup::AssociatedGroup() {} + +AssociatedGroup::AssociatedGroup(const AssociatedGroup& other) + : router_(other.router_) {} + +AssociatedGroup::~AssociatedGroup() {} + +AssociatedGroup& AssociatedGroup::operator=(const AssociatedGroup& other) { + if (this == &other) + return *this; + + router_ = other.router_; + return *this; +} + +void AssociatedGroup::CreateEndpointHandlePair( + internal::ScopedInterfaceEndpointHandle* local_endpoint, + internal::ScopedInterfaceEndpointHandle* remote_endpoint) { + if (!router_) + return; + + router_->CreateEndpointHandlePair(local_endpoint, remote_endpoint); +} + +} // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h b/mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h new file mode 100644 index 0000000..53d068f --- /dev/null +++ b/mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h
@@ -0,0 +1,132 @@ +// Copyright 2015 The Chromium Authors. 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_ASSOCIATED_INTERFACE_PTR_INTERNAL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_INTERNAL_H_ + +#include <algorithm> // For |std::swap()|. + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/public/cpp/bindings/associated_group.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" +#include "mojo/public/cpp/bindings/callback.h" +#include "mojo/public/cpp/bindings/lib/control_message_proxy.h" +#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" +#include "mojo/public/cpp/bindings/lib/interface_id.h" +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" + +namespace mojo { +namespace internal { + +template <typename Interface> +class AssociatedInterfacePtrState { + public: + AssociatedInterfacePtrState() : version_(0u) {} + + ~AssociatedInterfacePtrState() { + endpoint_client_.reset(); + proxy_.reset(); + } + + Interface* instance() { + // This will be null if the object is not bound. + return proxy_.get(); + } + + uint32_t version() const { return version_; } + + void QueryVersion(const Callback<void(uint32_t)>& callback) { + // It is safe to capture |this| because the callback won't be run after this + // object goes away. + auto callback_wrapper = [this, callback](uint32_t version) { + this->version_ = version; + callback.Run(version); + }; + + // Do a static cast in case the interface contains methods with the same + // name. + static_cast<ControlMessageProxy*>(proxy_.get()) + ->QueryVersion(callback_wrapper); + } + + void RequireVersion(uint32_t version) { + if (version <= version_) + return; + + version_ = version; + // Do a static cast in case the interface contains methods with the same + // name. + static_cast<ControlMessageProxy*>(proxy_.get())->RequireVersion(version); + } + + void Swap(AssociatedInterfacePtrState* other) { + using std::swap; + swap(other->endpoint_client_, endpoint_client_); + swap(other->proxy_, proxy_); + swap(other->version_, version_); + } + + void Bind(AssociatedInterfacePtrInfo<Interface> info) { + DCHECK(!endpoint_client_); + DCHECK(!proxy_); + DCHECK_EQ(0u, version_); + DCHECK(info.is_valid()); + + version_ = info.version(); + endpoint_client_.reset(new InterfaceEndpointClient( + AssociatedInterfacePtrInfoHelper::PassHandle(&info), nullptr, + make_scoped_ptr(new typename Interface::ResponseValidator_()))); + proxy_.reset(new Proxy(endpoint_client_.get())); + } + + // After this method is called, the object is in an invalid state and + // shouldn't be reused. + AssociatedInterfacePtrInfo<Interface> PassInterface() { + ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle(); + endpoint_client_.reset(); + proxy_.reset(); + + AssociatedInterfacePtrInfo<Interface> result; + result.set_version(version_); + AssociatedInterfacePtrInfoHelper::SetHandle(&result, handle.Pass()); + return result.Pass(); + } + + bool is_bound() const { return !!endpoint_client_; } + + bool encountered_error() const { + return endpoint_client_ ? endpoint_client_->encountered_error() : false; + } + + void set_connection_error_handler(const Closure& error_handler) { + DCHECK(endpoint_client_); + endpoint_client_->set_connection_error_handler(error_handler); + } + + // Returns true if bound and awaiting a response to a message. + bool has_pending_callbacks() const { + return endpoint_client_ && endpoint_client_->has_pending_responders(); + } + + AssociatedGroup* associated_group() { + return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; + } + + private: + using Proxy = typename Interface::Proxy_; + + scoped_ptr<InterfaceEndpointClient> endpoint_client_; + scoped_ptr<Proxy> proxy_; + + uint32_t version_; + + DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrState); +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_INTERNAL_H_
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc index 68d6035..b2fb4df3 100644 --- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc +++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/stl_util.h" +#include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/lib/multiplex_router.h" namespace mojo { @@ -117,6 +118,12 @@ handle_.router()->DetachEndpointClient(handle_); } +AssociatedGroup* InterfaceEndpointClient::associated_group() { + if (!associated_group_) + associated_group_ = handle_.router()->CreateAssociatedGroup(); + return associated_group_.get(); +} + ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!has_pending_responders());
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.h b/mojo/public/cpp/bindings/lib/interface_endpoint_client.h index b3f3f5a..260fd3b 100644 --- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.h +++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.h
@@ -18,8 +18,13 @@ #include "mojo/public/cpp/bindings/message_filter.h" namespace mojo { + +class AssociatedGroup; + namespace internal { +class MultiplexRouter; + // InterfaceEndpointClient handles message sending and receiving of an interface // endpoint, either the implementation side or the client side. // It should only be accessed and destructed on the creating thread. @@ -52,6 +57,7 @@ } MultiplexRouter* router() const { return handle_.router(); } + AssociatedGroup* associated_group(); // After this call the object is in an invalid state and shouldn't be reused. ScopedInterfaceEndpointHandle PassHandle(); @@ -94,6 +100,7 @@ bool HandleValidatedMessage(Message* message); ScopedInterfaceEndpointHandle handle_; + scoped_ptr<AssociatedGroup> associated_group_; MessageReceiverWithResponderStatus* const incoming_receiver_; scoped_ptr<MessageFilter> payload_validator_;
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc index a2b057be..c09fc17 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/stl_util.h" +#include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" namespace mojo { @@ -284,6 +285,17 @@ } } +scoped_ptr<AssociatedGroup> MultiplexRouter::CreateAssociatedGroup() { + scoped_ptr<AssociatedGroup> group(new AssociatedGroup); + group->router_ = this; + return group.Pass(); +} + +// static +MultiplexRouter* MultiplexRouter::GetRouter(AssociatedGroup* associated_group) { + return associated_group->router_.get(); +} + ScopedMessagePipeHandle MultiplexRouter::PassMessagePipe() { DCHECK(thread_checker_.CalledOnValidThread()); {
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h index d9e7323..fc0d27e 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.h +++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -27,6 +27,9 @@ #include "mojo/public/cpp/environment/environment.h" namespace mojo { + +class AssociatedGroup; + namespace internal { class InterfaceEndpointClient; @@ -85,6 +88,10 @@ // and notifies all interfaces running on this pipe. void RaiseError(); + scoped_ptr<AssociatedGroup> CreateAssociatedGroup(); + + static MultiplexRouter* GetRouter(AssociatedGroup* associated_group); + // --------------------------------------------------------------------------- // The following public methods are called on the creating thread.
diff --git a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc index 4a2a47b..6f30c94 100644 --- a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc +++ b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
@@ -35,12 +35,7 @@ ScopedInterfaceEndpointHandle& ScopedInterfaceEndpointHandle::operator=( ScopedInterfaceEndpointHandle&& other) { reset(); - - id_ = other.id_; - is_local_ = other.is_local_; - router_.swap(other.router_); - - other.id_ = kInvalidInterfaceId; + swap(other); return *this; } @@ -52,6 +47,7 @@ router_->CloseEndpointHandle(id_, is_local_); id_ = kInvalidInterfaceId; + is_local_ = true; router_ = nullptr; } @@ -66,6 +62,7 @@ InterfaceId result = id_; id_ = kInvalidInterfaceId; + is_local_ = true; router_ = nullptr; return result;
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index 5ec5d8d..9fd466a 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -9,6 +9,7 @@ sources = [ "array_unittest.cc", + "associated_interface_unittest.cc", "binding_callback_unittest.cc", "binding_unittest.cc", "bounds_checker_unittest.cc",
diff --git a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc new file mode 100644 index 0000000..d3686ec --- /dev/null +++ b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
@@ -0,0 +1,451 @@ +// Copyright 2015 The Chromium Authors. 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 "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/threading/thread.h" +#include "mojo/message_pump/message_pump_mojo.h" +#include "mojo/public/cpp/bindings/associated_binding.h" +#include "mojo/public/cpp/bindings/associated_group.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" +#include "mojo/public/cpp/bindings/associated_interface_request.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" +#include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { +namespace { + +using mojo::internal::AssociatedInterfacePtrInfoHelper; +using mojo::internal::AssociatedInterfaceRequestHelper; +using mojo::internal::MultiplexRouter; +using mojo::internal::ScopedInterfaceEndpointHandle; + +class IntegerSenderImpl : public IntegerSender { + public: + explicit IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request) + : binding_(this, request.Pass()) {} + + ~IntegerSenderImpl() override {} + + void set_notify_send_method_called( + const base::Callback<void(int32_t)>& callback) { + notify_send_method_called_ = callback; + } + + void Echo(int32_t value, const EchoCallback& callback) override { + callback.Run(value); + } + void Send(int32_t value) override { notify_send_method_called_.Run(value); } + + AssociatedBinding<IntegerSender>* binding() { return &binding_; } + + void set_connection_error_handler(const Closure& handler) { + binding_.set_connection_error_handler(handler); + } + + private: + AssociatedBinding<IntegerSender> binding_; + base::Callback<void(int32_t)> notify_send_method_called_; +}; + +class AssociatedInterfaceTest : public testing::Test { + public: + AssociatedInterfaceTest() : loop_(common::MessagePumpMojo::Create()) {} + ~AssociatedInterfaceTest() override { loop_.RunUntilIdle(); } + + void PumpMessages() { loop_.RunUntilIdle(); } + + template <typename T> + AssociatedInterfacePtrInfo<T> EmulatePassingAssociatedPtrInfo( + AssociatedInterfacePtrInfo<T> ptr_info, + scoped_refptr<MultiplexRouter> target) { + ScopedInterfaceEndpointHandle handle = + AssociatedInterfacePtrInfoHelper::PassHandle(&ptr_info); + CHECK(!handle.is_local()); + + ScopedInterfaceEndpointHandle new_handle = + target->CreateLocalEndpointHandle(handle.release()); + + AssociatedInterfacePtrInfo<T> result; + AssociatedInterfacePtrInfoHelper::SetHandle(&result, new_handle.Pass()); + result.set_version(ptr_info.version()); + return result.Pass(); + } + + template <typename T> + AssociatedInterfaceRequest<T> EmulatePassingAssociatedRequest( + AssociatedInterfaceRequest<T> request, + scoped_refptr<MultiplexRouter> target) { + ScopedInterfaceEndpointHandle handle = + AssociatedInterfaceRequestHelper::PassHandle(&request); + CHECK(!handle.is_local()); + + ScopedInterfaceEndpointHandle new_handle = + target->CreateLocalEndpointHandle(handle.release()); + + AssociatedInterfaceRequest<T> result; + AssociatedInterfaceRequestHelper::SetHandle(&result, new_handle.Pass()); + return result.Pass(); + } + + // Okay to call from any thread. + void QuitRunLoop(base::RunLoop* run_loop) { + if (loop_.task_runner()->BelongsToCurrentThread()) { + run_loop->Quit(); + } else { + loop_.PostTask( + FROM_HERE, + base::Bind(&AssociatedInterfaceTest::QuitRunLoop, + base::Unretained(this), base::Unretained(run_loop))); + } + } + + private: + base::MessageLoop loop_; +}; + +TEST_F(AssociatedInterfaceTest, InterfacesAtBothEnds) { + // Bind to the same pipe two associated interfaces, whose implementation lives + // at different ends. Test that the two don't interfere with each other. + + MessagePipe pipe; + scoped_refptr<MultiplexRouter> router0( + new MultiplexRouter(true, pipe.handle0.Pass())); + scoped_refptr<MultiplexRouter> router1( + new MultiplexRouter(false, pipe.handle1.Pass())); + + AssociatedInterfaceRequest<IntegerSender> request; + AssociatedInterfacePtrInfo<IntegerSender> ptr_info; + + router0->CreateAssociatedGroup()->CreateAssociatedInterface( + AssociatedGroup::WILL_PASS_PTR, &ptr_info, &request); + ptr_info = EmulatePassingAssociatedPtrInfo(ptr_info.Pass(), router1); + + IntegerSenderImpl impl0(request.Pass()); + AssociatedInterfacePtr<IntegerSender> ptr0; + ptr0.Bind(ptr_info.Pass()); + + router0->CreateAssociatedGroup()->CreateAssociatedInterface( + AssociatedGroup::WILL_PASS_REQUEST, &ptr_info, &request); + request = EmulatePassingAssociatedRequest(request.Pass(), router1); + + IntegerSenderImpl impl1(request.Pass()); + AssociatedInterfacePtr<IntegerSender> ptr1; + ptr1.Bind(ptr_info.Pass()); + + bool ptr0_callback_run = false; + ptr0->Echo(123, [&ptr0_callback_run](int32_t value) { + EXPECT_EQ(123, value); + ptr0_callback_run = true; + }); + + bool ptr1_callback_run = false; + ptr1->Echo(456, [&ptr1_callback_run](int32_t value) { + EXPECT_EQ(456, value); + ptr1_callback_run = true; + }); + + PumpMessages(); + EXPECT_TRUE(ptr0_callback_run); + EXPECT_TRUE(ptr1_callback_run); + + bool ptr0_error_callback_run = false; + ptr0.set_connection_error_handler( + [&ptr0_error_callback_run]() { ptr0_error_callback_run = true; }); + + impl0.binding()->Close(); + PumpMessages(); + EXPECT_TRUE(ptr0_error_callback_run); + + bool impl1_error_callback_run = false; + impl1.binding()->set_connection_error_handler( + [&impl1_error_callback_run]() { impl1_error_callback_run = true; }); + + ptr1.reset(); + PumpMessages(); + EXPECT_TRUE(impl1_error_callback_run); +} + +class TestSender { + public: + TestSender() + : sender_thread_("TestSender"), + next_sender_(nullptr), + max_value_to_send_(-1) { + base::Thread::Options thread_options; + thread_options.message_pump_factory = + base::Bind(&common::MessagePumpMojo::Create); + sender_thread_.StartWithOptions(thread_options); + } + + // The following three methods are called on the corresponding sender thread. + void SetUp(AssociatedInterfacePtrInfo<IntegerSender> ptr_info, + TestSender* next_sender, + int32_t max_value_to_send) { + CHECK(sender_thread_.task_runner()->BelongsToCurrentThread()); + + ptr_.Bind(ptr_info.Pass()); + next_sender_ = next_sender ? next_sender : this; + max_value_to_send_ = max_value_to_send; + } + + void Send(int32_t value) { + CHECK(sender_thread_.task_runner()->BelongsToCurrentThread()); + + if (value > max_value_to_send_) + return; + + ptr_->Send(value); + + next_sender_->sender_thread()->task_runner()->PostTask( + FROM_HERE, + base::Bind(&TestSender::Send, base::Unretained(next_sender_), ++value)); + } + + void TearDown() { + CHECK(sender_thread_.task_runner()->BelongsToCurrentThread()); + + ptr_.reset(); + } + + base::Thread* sender_thread() { return &sender_thread_; } + + private: + base::Thread sender_thread_; + TestSender* next_sender_; + int32_t max_value_to_send_; + + AssociatedInterfacePtr<IntegerSender> ptr_; +}; + +class TestReceiver { + public: + TestReceiver() : receiver_thread_("TestReceiver"), max_value_to_receive_(-1) { + base::Thread::Options thread_options; + thread_options.message_pump_factory = + base::Bind(&common::MessagePumpMojo::Create); + receiver_thread_.StartWithOptions(thread_options); + } + + void SetUp(AssociatedInterfaceRequest<IntegerSender> request0, + AssociatedInterfaceRequest<IntegerSender> request1, + int32_t max_value_to_receive, + const base::Closure& notify_finish) { + CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread()); + + impl0_.reset(new IntegerSenderImpl(request0.Pass())); + impl0_->set_notify_send_method_called( + base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this))); + impl1_.reset(new IntegerSenderImpl(request1.Pass())); + impl1_->set_notify_send_method_called( + base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this))); + + max_value_to_receive_ = max_value_to_receive; + notify_finish_ = notify_finish; + } + + void TearDown() { + CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread()); + + impl0_.reset(); + impl1_.reset(); + } + + base::Thread* receiver_thread() { return &receiver_thread_; } + const std::vector<int32_t>& values() const { return values_; } + + private: + void SendMethodCalled(int32_t value) { + values_.push_back(value); + + if (value >= max_value_to_receive_) + notify_finish_.Run(); + } + + base::Thread receiver_thread_; + int32_t max_value_to_receive_; + + scoped_ptr<IntegerSenderImpl> impl0_; + scoped_ptr<IntegerSenderImpl> impl1_; + + std::vector<int32_t> values_; + + base::Closure notify_finish_; +}; + +TEST_F(AssociatedInterfaceTest, MultiThreadAccess) { + // Set up four associated interfaces on a message pipe. Use the inteface + // pointers on four threads in parallel; run the interface implementations on + // two threads. Test that multi-threaded access works. + + const int32_t kMaxValue = 1000; + MessagePipe pipe; + scoped_refptr<MultiplexRouter> router0( + new MultiplexRouter(true, pipe.handle0.Pass())); + scoped_refptr<MultiplexRouter> router1( + new MultiplexRouter(false, pipe.handle1.Pass())); + + AssociatedInterfaceRequest<IntegerSender> requests[4]; + AssociatedInterfacePtrInfo<IntegerSender> ptr_infos[4]; + + for (size_t i = 0; i < 4; ++i) { + router0->CreateAssociatedGroup()->CreateAssociatedInterface( + AssociatedGroup::WILL_PASS_PTR, &ptr_infos[i], &requests[i]); + ptr_infos[i] = + EmulatePassingAssociatedPtrInfo(ptr_infos[i].Pass(), router1); + } + + TestSender senders[4]; + for (size_t i = 0; i < 4; ++i) { + senders[i].sender_thread()->task_runner()->PostTask( + FROM_HERE, base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]), + base::Passed(&ptr_infos[i]), nullptr, + static_cast<int32_t>(kMaxValue * (i + 1) / 4))); + } + + base::RunLoop run_loop; + TestReceiver receivers[2]; + for (size_t i = 0; i < 2; ++i) { + receivers[i].receiver_thread()->task_runner()->PostTask( + FROM_HERE, + base::Bind( + &TestReceiver::SetUp, base::Unretained(&receivers[i]), + base::Passed(&requests[2 * i]), base::Passed(&requests[2 * i + 1]), + kMaxValue, + base::Bind(&AssociatedInterfaceTest::QuitRunLoop, + base::Unretained(this), base::Unretained(&run_loop)))); + } + + for (size_t i = 0; i < 4; ++i) { + senders[i].sender_thread()->task_runner()->PostTask( + FROM_HERE, base::Bind(&TestSender::Send, base::Unretained(&senders[i]), + static_cast<int32_t>(kMaxValue * i / 4 + 1))); + } + + run_loop.Run(); + + for (size_t i = 0; i < 4; ++i) { + base::RunLoop run_loop; + senders[i].sender_thread()->task_runner()->PostTaskAndReply( + FROM_HERE, + base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])), + base::Bind(&AssociatedInterfaceTest::QuitRunLoop, + base::Unretained(this), base::Unretained(&run_loop))); + run_loop.Run(); + } + + for (size_t i = 0; i < 2; ++i) { + base::RunLoop run_loop; + receivers[i].receiver_thread()->task_runner()->PostTaskAndReply( + FROM_HERE, + base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])), + base::Bind(&AssociatedInterfaceTest::QuitRunLoop, + base::Unretained(this), base::Unretained(&run_loop))); + run_loop.Run(); + } + + EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size()); + EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size()); + + std::vector<int32_t> all_values; + all_values.insert(all_values.end(), receivers[0].values().begin(), + receivers[0].values().end()); + all_values.insert(all_values.end(), receivers[1].values().begin(), + receivers[1].values().end()); + + std::sort(all_values.begin(), all_values.end()); + for (size_t i = 0; i < all_values.size(); ++i) + ASSERT_EQ(static_cast<int32_t>(i + 1), all_values[i]); +} + +TEST_F(AssociatedInterfaceTest, FIFO) { + // Set up four associated interfaces on a message pipe. Use the inteface + // pointers on four threads; run the interface implementations on two threads. + // Take turns to make calls using the four pointers. Test that FIFO-ness is + // preserved. + + const int32_t kMaxValue = 100; + MessagePipe pipe; + scoped_refptr<MultiplexRouter> router0( + new MultiplexRouter(true, pipe.handle0.Pass())); + scoped_refptr<MultiplexRouter> router1( + new MultiplexRouter(false, pipe.handle1.Pass())); + + AssociatedInterfaceRequest<IntegerSender> requests[4]; + AssociatedInterfacePtrInfo<IntegerSender> ptr_infos[4]; + + for (size_t i = 0; i < 4; ++i) { + router0->CreateAssociatedGroup()->CreateAssociatedInterface( + AssociatedGroup::WILL_PASS_PTR, &ptr_infos[i], &requests[i]); + ptr_infos[i] = + EmulatePassingAssociatedPtrInfo(ptr_infos[i].Pass(), router1); + } + + TestSender senders[4]; + for (size_t i = 0; i < 4; ++i) { + senders[i].sender_thread()->task_runner()->PostTask( + FROM_HERE, + base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]), + base::Passed(&ptr_infos[i]), + base::Unretained(&senders[(i + 1) % 4]), kMaxValue)); + } + + base::RunLoop run_loop; + TestReceiver receivers[2]; + for (size_t i = 0; i < 2; ++i) { + receivers[i].receiver_thread()->task_runner()->PostTask( + FROM_HERE, + base::Bind( + &TestReceiver::SetUp, base::Unretained(&receivers[i]), + base::Passed(&requests[2 * i]), base::Passed(&requests[2 * i + 1]), + kMaxValue, + base::Bind(&AssociatedInterfaceTest::QuitRunLoop, + base::Unretained(this), base::Unretained(&run_loop)))); + } + + senders[0].sender_thread()->task_runner()->PostTask( + FROM_HERE, + base::Bind(&TestSender::Send, base::Unretained(&senders[0]), 1)); + + run_loop.Run(); + + for (size_t i = 0; i < 4; ++i) { + base::RunLoop run_loop; + senders[i].sender_thread()->task_runner()->PostTaskAndReply( + FROM_HERE, + base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])), + base::Bind(&AssociatedInterfaceTest::QuitRunLoop, + base::Unretained(this), base::Unretained(&run_loop))); + run_loop.Run(); + } + + for (size_t i = 0; i < 2; ++i) { + base::RunLoop run_loop; + receivers[i].receiver_thread()->task_runner()->PostTaskAndReply( + FROM_HERE, + base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])), + base::Bind(&AssociatedInterfaceTest::QuitRunLoop, + base::Unretained(this), base::Unretained(&run_loop))); + run_loop.Run(); + } + + EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size()); + EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size()); + + for (size_t i = 0; i < 2; ++i) { + for (size_t j = 1; j < receivers[i].values().size(); ++j) + EXPECT_LT(receivers[i].values()[j - 1], receivers[i].values()[j]); + } +} + +} // namespace +} // namespace test +} // namespace mojo
diff --git a/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom b/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom index d81a919..62ff7a7c 100644 --- a/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom +++ b/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom
@@ -28,3 +28,13 @@ PassUnion(UnionContainsAssociated foo_union) => (UnionContainsAssociated foo_union); }; + +interface IntegerSender { + Echo(int32 value) => (int32 value); + Send(int32 value); +}; + +interface IntegerSenderConnection { + GetSender(associated IntegerSender& sender); + AsyncGetSender() => (associated IntegerSender sender); +};
diff --git a/mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java index 2939aa5..7e148ac 100644 --- a/mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java +++ b/mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java
@@ -47,9 +47,6 @@ // has no obligation to kill the application process between destroying and restarting the // activity. If the application process is kept alive, initialization parameters sent with // the intent will be stale. - // TODO(qsr): We should be passing application context here as required by - // InitApplicationContext on the native side. Currently we can't, as PlatformViewportAndroid - // relies on this being the activity context. ShellMain.ensureInitialized(this, parameters); ShellMain.start(); }
diff --git a/mojo/runner/android/apk/src/org/chromium/mojo/shell/ShellMain.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/ShellMain.java index 942c19c..d0c2b6ee 100644 --- a/mojo/runner/android/apk/src/org/chromium/mojo/shell/ShellMain.java +++ b/mojo/runner/android/apk/src/org/chromium/mojo/shell/ShellMain.java
@@ -11,6 +11,7 @@ import android.os.Bundle; import android.util.Log; +import org.chromium.base.ContextUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -38,24 +39,22 @@ /** * Initializes the native system. **/ - public static void ensureInitialized(Context applicationContext, String[] parameters) { + public static void ensureInitialized(Context context, String[] parameters) { if (sInitialized) return; - File cachedAppsDir = getCachedAppsDir(applicationContext); + File cachedAppsDir = getCachedAppsDir(context); try { - final File timestamp = - FileHelper.prepareDirectoryForAssets(applicationContext, cachedAppsDir); - for (String assetPath : FileHelper.getAssetsList(applicationContext)) { - FileHelper.extractFromAssets(applicationContext, assetPath, cachedAppsDir, - FileHelper.FileType.PERMANENT); + final File timestamp = FileHelper.prepareDirectoryForAssets(context, cachedAppsDir); + for (String assetPath : FileHelper.getAssetsList(context)) { + FileHelper.extractFromAssets( + context, assetPath, cachedAppsDir, FileHelper.FileType.PERMANENT); } - ApplicationInfo ai = applicationContext.getPackageManager().getApplicationInfo( - applicationContext.getPackageName(), PackageManager.GET_META_DATA); + ApplicationInfo ai = context.getPackageManager().getApplicationInfo( + context.getPackageName(), PackageManager.GET_META_DATA); Bundle bundle = ai.metaData; String mojo_lib = bundle.getString(MOJO_LIB_KEY); FileHelper.createTimestampIfNecessary(timestamp); - File mojoShell = - new File(applicationContext.getApplicationInfo().nativeLibraryDir, mojo_lib); + File mojoShell = new File(context.getApplicationInfo().nativeLibraryDir, mojo_lib); List<String> parametersList = new ArrayList<String>(); // Program name. @@ -63,10 +62,10 @@ parametersList.addAll(Arrays.asList(parameters)); } - nativeInit(applicationContext, mojoShell.getAbsolutePath(), + ContextUtils.initApplicationContext(context.getApplicationContext()); + nativeInit(context, mojoShell.getAbsolutePath(), parametersList.toArray(new String[parametersList.size()]), - cachedAppsDir.getAbsolutePath(), - getTmpDir(applicationContext).getAbsolutePath()); + cachedAppsDir.getAbsolutePath(), getTmpDir(context).getAbsolutePath()); sInitialized = true; } catch (Exception e) { Log.e(TAG, "ShellMain initialization failed.", e);
diff --git a/mojo/runner/android/main.cc b/mojo/runner/android/main.cc index 3980c22..5e4710f 100644 --- a/mojo/runner/android/main.cc +++ b/mojo/runner/android/main.cc
@@ -112,8 +112,6 @@ base::android::ConvertJavaStringToUTF8(env, j_tmp_dir).c_str(), 1); DCHECK_EQ(return_value, 0); - base::android::InitApplicationContext(env, activity); - std::vector<std::string> parameters; parameters.push_back( base::android::ConvertJavaStringToUTF8(env, mojo_shell_path));
diff --git a/mojo/runner/context.cc b/mojo/runner/context.cc index a21323b0..b86e29b 100644 --- a/mojo/runner/context.cc +++ b/mojo/runner/context.cc
@@ -54,6 +54,10 @@ class Setup { public: Setup() { +#if defined(OS_WIN) + embedder::PreInitializeParentProcess(); +#endif + embedder::Init(); }
diff --git a/mojo/runner/host/child_process.cc b/mojo/runner/host/child_process.cc index 8d2ab95..7c157b6 100644 --- a/mojo/runner/host/child_process.cc +++ b/mojo/runner/host/child_process.cc
@@ -21,6 +21,8 @@ #include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" #include "base/threading/thread_checker.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/core.h" @@ -44,6 +46,10 @@ namespace { +void DidCreateChannel(embedder::ChannelInfo* channel_info) { + DVLOG(2) << "ChildControllerImpl::DidCreateChannel()"; +} + // Blocker --------------------------------------------------------------------- // Blocks a thread until another thread unblocks it, at which point it unblocks @@ -102,6 +108,10 @@ ~AppContext() override {} void Init() { +#if defined(OS_WIN) + embedder::PreInitializeChildProcess(); +#endif + // Initialize Mojo before starting any threads. embedder::Init(); @@ -193,22 +203,16 @@ // etc. static void Init(AppContext* app_context, base::NativeLibrary app_library, - embedder::ScopedPlatformHandle platform_channel, + ScopedMessagePipeHandle host_message_pipe, const Blocker::Unblocker& unblocker) { DCHECK(app_context); - DCHECK(platform_channel.is_valid()); + DCHECK(host_message_pipe.is_valid()); DCHECK(!app_context->controller()); scoped_ptr<ChildControllerImpl> impl( new ChildControllerImpl(app_context, app_library, unblocker)); - ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( - platform_channel.Pass(), - base::Bind(&ChildControllerImpl::DidCreateChannel, - base::Unretained(impl.get())), - base::ThreadTaskRunnerHandle::Get())); - impl->Bind(host_message_pipe.Pass()); app_context->set_controller(impl.Pass()); @@ -251,13 +255,6 @@ binding_.set_connection_error_handler([this]() { OnConnectionError(); }); } - // 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( base::NativeLibrary app_library, InterfaceRequest<Application> application_request) { @@ -278,6 +275,69 @@ DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); }; +#if defined(OS_LINUX) && !defined(OS_ANDROID) +scoped_ptr<mojo::runner::LinuxSandbox> InitializeSandbox() { + using sandbox::syscall_broker::BrokerFilePermission; + // Warm parts of base in the copy of base in the mojo runner. + base::RandUint64(); + base::SysInfo::AmountOfPhysicalMemory(); + base::SysInfo::MaxSharedMemorySize(); + base::SysInfo::NumberOfProcessors(); + + // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to + // spy on other shared memory using processes. This is a temporary hack + // so that we have some sandbox until we have proper shared memory + // support integrated into mojo. + std::vector<BrokerFilePermission> permissions; + permissions.push_back( + BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/")); + scoped_ptr<mojo::runner::LinuxSandbox> sandbox( + new mojo::runner::LinuxSandbox(permissions)); + sandbox->Warmup(); + sandbox->EngageNamespaceSandbox(); + sandbox->EngageSeccompSandbox(); + sandbox->Seal(); + return sandbox.Pass(); +} +#endif + +ScopedMessagePipeHandle InitializeHostMessagePipe( + embedder::ScopedPlatformHandle platform_channel, + scoped_refptr<base::TaskRunner> io_task_runner) { + ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( + platform_channel.Pass(), base::Bind(&DidCreateChannel), io_task_runner)); + +#if defined(OS_WIN) + if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { + // When using the new Mojo EDK, each message pipe is backed by a platform + // handle. The one platform handle that comes on the command line is used + // to bind to the ChildController interface. However we also want a + // platform handle to setup the communication channel by which we exchange + // handles to/from tokens, which is needed for sandboxed Windows + // processes. + char token_serializer_handle[10]; + MojoHandleSignalsState state; + MojoResult rv = + MojoWait(host_message_pipe.get().value(), MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state); + CHECK_EQ(MOJO_RESULT_OK, rv); + uint32_t num_bytes = arraysize(token_serializer_handle); + rv = MojoReadMessage(host_message_pipe.get().value(), + token_serializer_handle, &num_bytes, nullptr, 0, + MOJO_READ_MESSAGE_FLAG_NONE); + CHECK_EQ(MOJO_RESULT_OK, rv); + + edk::ScopedPlatformHandle token_serializer_channel = + edk::PlatformChannelPair::PassClientHandleFromParentProcessFromString( + std::string(token_serializer_handle, num_bytes)); + CHECK(token_serializer_channel.is_valid()); + embedder::SetParentPipeHandle(token_serializer_channel.release().handle); + } +#endif + + return host_message_pipe.Pass(); +} + } // namespace int ChildProcessMain() { @@ -286,41 +346,19 @@ *base::CommandLine::ForCurrentProcess(); #if defined(OS_LINUX) && !defined(OS_ANDROID) - using sandbox::syscall_broker::BrokerFilePermission; scoped_ptr<mojo::runner::LinuxSandbox> sandbox; #endif base::NativeLibrary app_library = 0; - if (command_line.HasSwitch(switches::kChildProcess)) { - // Load the application library before we engage the sandbox. - app_library = mojo::runner::LoadNativeApplication( - command_line.GetSwitchValuePath(switches::kChildProcess)); + // Load the application library before we engage the sandbox. + app_library = mojo::runner::LoadNativeApplication( + command_line.GetSwitchValuePath(switches::kChildProcess)); - base::i18n::InitializeICU(); - CallLibraryEarlyInitialization(app_library); - + base::i18n::InitializeICU(); + CallLibraryEarlyInitialization(app_library); #if defined(OS_LINUX) && !defined(OS_ANDROID) - if (command_line.HasSwitch(switches::kEnableSandbox)) { - // Warm parts of base in the copy of base in the mojo runner. - base::RandUint64(); - base::SysInfo::AmountOfPhysicalMemory(); - base::SysInfo::MaxSharedMemorySize(); - base::SysInfo::NumberOfProcessors(); - - // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to - // spy on other shared memory using processes. This is a temporary hack - // so that we have some sandbox until we have proper shared memory - // support integrated into mojo. - std::vector<BrokerFilePermission> permissions; - permissions.push_back( - BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/")); - sandbox.reset(new mojo::runner::LinuxSandbox(permissions)); - sandbox->Warmup(); - sandbox->EngageNamespaceSandbox(); - sandbox->EngageSeccompSandbox(); - sandbox->Seal(); - } + if (command_line.HasSwitch(switches::kEnableSandbox)) + sandbox = InitializeSandbox(); #endif - } embedder::ScopedPlatformHandle platform_channel = embedder::PlatformChannelPair::PassClientHandleFromParentProcess( @@ -331,12 +369,14 @@ AppContext app_context; app_context.Init(); + ScopedMessagePipeHandle host_message_pipe = InitializeHostMessagePipe( + platform_channel.Pass(), app_context.io_runner()); Blocker blocker; app_context.controller_runner()->PostTask( FROM_HERE, base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context), - base::Unretained(app_library), base::Passed(&platform_channel), - blocker.GetUnblocker())); + base::Unretained(app_library), + base::Passed(&host_message_pipe), blocker.GetUnblocker())); // This will block, then run whatever the controller wants. blocker.Block();
diff --git a/mojo/runner/host/child_process_host.cc b/mojo/runner/host/child_process_host.cc index 10a2439..ee92141 100644 --- a/mojo/runner/host/child_process_host.cc +++ b/mojo/runner/host/child_process_host.cc
@@ -39,8 +39,15 @@ channel_info_(nullptr), start_child_process_event_(false, false), weak_factory_(this) { - platform_channel_ = platform_channel_pair_.PassServerHandle(); - CHECK(platform_channel_.is_valid()); +#if defined(OS_WIN) + if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) + serializer_platform_channel_pair_.reset(new edk::PlatformChannelPair(true)); +#endif + + child_message_pipe_ = embedder::CreateChannel( + platform_channel_pair_.PassServerHandle(), + base::Bind(&ChildProcessHost::DidCreateChannel, base::Unretained(this)), + base::ThreadTaskRunnerHandle::Get()); } ChildProcessHost::ChildProcessHost(ScopedHandle channel) @@ -61,14 +68,27 @@ void ChildProcessHost::Start() { DCHECK(!child_process_.IsValid()); - DCHECK(platform_channel_.is_valid()); + DCHECK(child_message_pipe_.is_valid()); - ScopedMessagePipeHandle handle(embedder::CreateChannel( - platform_channel_.Pass(), base::Bind(&ChildProcessHost::DidCreateChannel, - weak_factory_.GetWeakPtr()), - base::ThreadTaskRunnerHandle::Get())); +#if defined(OS_WIN) + if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) { + std::string client_handle_as_string = + serializer_platform_channel_pair_ + ->PrepareToPassClientHandleToChildProcessAsString( + &handle_passing_info_); + // We can't send the MP for the token serializer implementation as a + // platform handle, because that would require the other side to use the + // token initializer itself! So instead we send it as a string. + MojoResult rv = MojoWriteMessage( + child_message_pipe_.get().value(), client_handle_as_string.c_str(), + static_cast<uint32_t>(client_handle_as_string.size()), nullptr, 0, + MOJO_WRITE_MESSAGE_FLAG_NONE); + DCHECK_EQ(rv, MOJO_RESULT_OK); + } +#endif - controller_.Bind(InterfacePtrInfo<ChildController>(handle.Pass(), 0u)); + controller_.Bind( + InterfacePtrInfo<ChildController>(child_message_pipe_.Pass(), 0u)); launch_process_runner_->PostTaskAndReply( FROM_HERE, @@ -133,14 +153,13 @@ if (start_sandboxed_) child_command_line.AppendSwitch(switches::kEnableSandbox); - embedder::HandlePassingInformation handle_passing_info; platform_channel_pair_.PrepareToPassClientHandleToChildProcess( - &child_command_line, &handle_passing_info); + &child_command_line, &handle_passing_info_); base::LaunchOptions options; #if defined(OS_WIN) if (base::win::GetVersion() >= base::win::VERSION_VISTA) { - options.handles_to_inherit = &handle_passing_info; + options.handles_to_inherit = &handle_passing_info_; } else { #if defined(OFFICIAL_BUILD) CHECK(false) << "Launching mojo process with inherit_handles is insecure!"; @@ -159,16 +178,16 @@ // (i.e. by apptest_runner.py) then a real handle is used. In that case, we do // want to add it to the list of handles that is inherited. if (GetFileType(options.stdout_handle) != FILE_TYPE_CHAR) - handle_passing_info.push_back(options.stdout_handle); + handle_passing_info_.push_back(options.stdout_handle); if (GetFileType(options.stderr_handle) != FILE_TYPE_CHAR && options.stdout_handle != options.stdout_handle) { - handle_passing_info.push_back(options.stderr_handle); + handle_passing_info_.push_back(options.stderr_handle); } #elif defined(OS_POSIX) - handle_passing_info.push_back(std::make_pair(STDIN_FILENO, STDIN_FILENO)); - handle_passing_info.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO)); - handle_passing_info.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO)); - options.fds_to_remap = &handle_passing_info; + handle_passing_info_.push_back(std::make_pair(STDIN_FILENO, STDIN_FILENO)); + handle_passing_info_.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO)); + handle_passing_info_.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO)); + options.fds_to_remap = &handle_passing_info_; #endif DVLOG(2) << "Launching child with command line: " << child_command_line.GetCommandLineString(); @@ -184,8 +203,19 @@ #endif child_process_ = base::LaunchProcess(child_command_line, options); - if (child_process_.IsValid()) + if (child_process_.IsValid()) { platform_channel_pair_.ChildProcessLaunched(); +#if defined(OS_WIN) + if (serializer_platform_channel_pair_.get()) { + serializer_platform_channel_pair_->ChildProcessLaunched(); + mojo::embedder::ChildProcessLaunched( + child_process_.Handle(), + serializer_platform_channel_pair_->PassServerHandle() + .release() + .handle); + } +#endif + } start_child_process_event_.Signal(); }
diff --git a/mojo/runner/host/child_process_host.h b/mojo/runner/host/child_process_host.h index a4d15103..65ca9c4 100644 --- a/mojo/runner/host/child_process_host.h +++ b/mojo/runner/host/child_process_host.h
@@ -10,6 +10,8 @@ #include "base/memory/weak_ptr.h" #include "base/process/process.h" #include "base/synchronization/waitable_event.h" +#include "mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/public/cpp/system/message_pipe.h" #include "mojo/runner/child/child_controller.mojom.h" #include "mojo/runner/host/child_process_host.h" #include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h" @@ -70,22 +72,29 @@ // Callback for |embedder::CreateChannel()|. void DidCreateChannel(embedder::ChannelInfo* channel_info); - base::TaskRunner* const launch_process_runner_; + scoped_refptr<base::TaskRunner> launch_process_runner_; bool start_sandboxed_; const base::FilePath app_path_; base::Process child_process_; + // Used for the ChildController binding. embedder::PlatformChannelPair platform_channel_pair_; ChildControllerPtr controller_; embedder::ChannelInfo* channel_info_; ChildController::StartAppCallback on_app_complete_; + embedder::HandlePassingInformation handle_passing_info_; + +#if defined(OS_WIN) + // Used only when --use-new-edk is specified, as a communication channel for + // TokenSerializer. + scoped_ptr<edk::PlatformChannelPair> serializer_platform_channel_pair_; +#endif // Since Start() calls a method on another thread, we use an event to block // the main thread if it tries to destruct |this| while launching the process. base::WaitableEvent start_child_process_event_; - // Platform-specific "pipe" to the child process. Valid immediately after - // creation. - embedder::ScopedPlatformHandle platform_channel_; + // A message pipe to the child process. Valid immediately after creation. + mojo::ScopedMessagePipeHandle child_message_pipe_; base::WeakPtrFactory<ChildProcessHost> weak_factory_;
diff --git a/mojo/services/network/url_loader_impl_apptest.cc b/mojo/services/network/url_loader_impl_apptest.cc index 0fe1749..0b9de67 100644 --- a/mojo/services/network/url_loader_impl_apptest.cc +++ b/mojo/services/network/url_loader_impl_apptest.cc
@@ -49,32 +49,28 @@ void Start() override { status_ = STARTED; } - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override { + int ReadRawData(net::IOBuffer* buf, int buf_size) override { status_ = READING; buf_size_ = buf_size; - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; + return net::ERR_IO_PENDING; } void NotifyHeadersComplete() { net::URLRequestJob::NotifyHeadersComplete(); } void NotifyReadComplete(int bytes_read) { if (bytes_read < 0) { - NotifyDone(net::URLRequestStatus( - net::URLRequestStatus::FromError(net::ERR_FAILED))); - net::URLRequestJob::NotifyReadComplete(0); + // Map errors to net::ERR_FAILED. + ReadRawDataComplete(net::ERR_FAILED); // Set this after calling ReadRawDataComplete since that ends up calling // ReadRawData. status_ = COMPLETED; } else if (bytes_read == 0) { - NotifyDone(net::URLRequestStatus()); - net::URLRequestJob::NotifyReadComplete(bytes_read); + ReadRawDataComplete(bytes_read); // Set this after calling ReadRawDataComplete since that ends up calling // ReadRawData. status_ = COMPLETED; } else { - SetStatus(net::URLRequestStatus()); - net::URLRequestJob::NotifyReadComplete(bytes_read); + ReadRawDataComplete(bytes_read); // Set this after calling ReadRawDataComplete since that ends up calling // ReadRawData. status_ = STARTED;
diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn index c1c6aae..7036806 100644 --- a/mojo/shell/BUILD.gn +++ b/mojo/shell/BUILD.gn
@@ -50,7 +50,6 @@ "//url", ] deps = [ - ":interfaces", "//base/third_party/dynamic_annotations", "//crypto:crypto", "//mojo/application/public/cpp:sources", @@ -115,12 +114,6 @@ ] } -mojom("interfaces") { - sources = [ - "application_manager.mojom", - ] -} - mojo_native_application("apptests") { output_name = "mojo_shell_apptests" testonly = true @@ -157,11 +150,11 @@ "//base", "//base:base_static", "//mojo/application/public/cpp", + "//mojo/application/public/interfaces", "//mojo/common:common_base", "//mojo/converters/network", "//mojo/runner:init", "//mojo/runner/child:test_native_main", - "//mojo/shell:interfaces", "//third_party/mojo/src/mojo/edk/system", ] }
diff --git a/mojo/shell/application_manager.cc b/mojo/shell/application_manager.cc index 1e9e2a7d..89f248e9 100644 --- a/mojo/shell/application_manager.cc +++ b/mojo/shell/application_manager.cc
@@ -117,14 +117,16 @@ } void ApplicationManager::CreateInstanceForHandle(ScopedHandle channel, - const GURL& url) { + const GURL& url, + CapabilityFilterPtr filter) { // Instances created by others are considered unique, and thus have no // identity. As such they cannot be connected to by anyone else, and so we // never call ConnectToClient(). // TODO(beng): GetPermissiveCapabilityFilter() here obviously cannot make it // to production. See note in application_manager.mojom. // http://crbug.com/555392 - Identity target_id(url, std::string(), GetPermissiveCapabilityFilter()); + CapabilityFilter local_filter = filter->filter.To<CapabilityFilter>(); + Identity target_id(url, std::string(), local_filter); InterfaceRequest<Application> application_request = CreateInstance(target_id, base::Closure(), nullptr); NativeRunner* runner =
diff --git a/mojo/shell/application_manager.h b/mojo/shell/application_manager.h index 431f5e2..32680d09 100644 --- a/mojo/shell/application_manager.h +++ b/mojo/shell/application_manager.h
@@ -92,7 +92,9 @@ ApplicationInstance* GetApplicationInstance(const Identity& identity) const; - void CreateInstanceForHandle(ScopedHandle channel, const GURL& url); + void CreateInstanceForHandle(ScopedHandle channel, + const GURL& url, + CapabilityFilterPtr filter); private: using IdentityToInstanceMap = std::map<Identity, ApplicationInstance*>;
diff --git a/mojo/shell/application_manager.mojom b/mojo/shell/application_manager.mojom deleted file mode 100644 index fbd2be76..0000000 --- a/mojo/shell/application_manager.mojom +++ /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. - -module mojo.shell.mojom; - -interface ApplicationManager { - // Instructs the ApplicationManager to create an instance for an existing - // process at the other end of |channel|, and perform applicable - // initialization. This assumes the target process will bind the other end of - // channel to an implementation of ChildController and bind an Application - // request there. - // TODO(beng): we should probably have an Identity mojom struct. - // TODO(beng): for this to be used in production, it's going to have to take - // a fully qualified Identity complete with CapabilityFilter, - // otherwise child processes registered with the shell will be - // able to request any application/service. - // http://crbug.com/555392 - CreateInstanceForHandle(handle channel, string url); -};
diff --git a/mojo/shell/application_manager_apptest_driver.cc b/mojo/shell/application_manager_apptest_driver.cc index dce9762..b0aa8fab 100644 --- a/mojo/shell/application_manager_apptest_driver.cc +++ b/mojo/shell/application_manager_apptest_driver.cc
@@ -17,11 +17,11 @@ #include "mojo/application/public/cpp/application_delegate.h" #include "mojo/application/public/cpp/application_impl.h" #include "mojo/application/public/cpp/interface_factory.h" +#include "mojo/application/public/interfaces/application_manager.mojom.h" #include "mojo/common/weak_binding_set.h" #include "mojo/converters/network/network_type_converters.h" #include "mojo/runner/child/test_native_main.h" #include "mojo/runner/init.h" -#include "mojo/shell/application_manager.mojom.h" #include "mojo/shell/application_manager_apptests.mojom.h" #include "third_party/mojo/src/mojo/edk/embedder/embedder.h" #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" @@ -79,9 +79,15 @@ weak_factory_.GetWeakPtr()), base::ThreadTaskRunnerHandle::Get())); + mojo::CapabilityFilterPtr filter(mojo::CapabilityFilter::New()); + mojo::Array<mojo::String> test_interfaces; + test_interfaces.push_back( + mojo::shell::test::mojom::CreateInstanceForHandleTest::Name_); + filter->filter.insert("mojo:mojo_shell_apptests", test_interfaces.Pass()); application_manager->CreateInstanceForHandle( mojo::ScopedHandle(mojo::Handle(handle.release().value())), - "exe:application_manager_apptest_target"); + "exe:application_manager_apptest_target", + filter.Pass()); // Put the other end on the command line used to launch the target. platform_channel_pair.PrepareToPassClientHandleToChildProcess( &child_command_line, &handle_passing_info);
diff --git a/mojo/shell/application_manager_apptest_target.cc b/mojo/shell/application_manager_apptest_target.cc index fa80ce7..f6eea3d 100644 --- a/mojo/shell/application_manager_apptest_target.cc +++ b/mojo/shell/application_manager_apptest_target.cc
@@ -7,7 +7,6 @@ #include "mojo/application/public/cpp/application_connection.h" #include "mojo/application/public/cpp/application_delegate.h" #include "mojo/application/public/cpp/application_impl.h" -#include "mojo/converters/network/network_type_converters.h" #include "mojo/runner/child/test_native_main.h" #include "mojo/runner/init.h" #include "mojo/shell/application_manager_apptests.mojom.h" @@ -25,9 +24,7 @@ // mojo::ApplicationDelegate: void Initialize(mojo::ApplicationImpl* app) override { CreateInstanceForHandleTestPtr service; - mojo::ApplicationImpl::ConnectParams params( - std::string("mojo:mojo_shell_apptests")); - app->ConnectToService(¶ms, &service); + app->ConnectToService("mojo:mojo_shell_apptests", &service); service->Ping("From Target"); } bool ConfigureIncomingConnection(
diff --git a/mojo/shell/shell_application_delegate.cc b/mojo/shell/shell_application_delegate.cc index 8c9faa7..445bc37 100644 --- a/mojo/shell/shell_application_delegate.cc +++ b/mojo/shell/shell_application_delegate.cc
@@ -28,9 +28,11 @@ bindings_.AddBinding(this, request.Pass()); } -void ShellApplicationDelegate::CreateInstanceForHandle(ScopedHandle channel, - const String& url) { - manager_->CreateInstanceForHandle(channel.Pass(), GURL(url)); +void ShellApplicationDelegate::CreateInstanceForHandle( + ScopedHandle channel, + const String& url, + CapabilityFilterPtr filter) { + manager_->CreateInstanceForHandle(channel.Pass(), GURL(url), filter.Pass()); } } // namespace shell
diff --git a/mojo/shell/shell_application_delegate.h b/mojo/shell/shell_application_delegate.h index c39691e..fcf1e29 100644 --- a/mojo/shell/shell_application_delegate.h +++ b/mojo/shell/shell_application_delegate.h
@@ -9,8 +9,8 @@ #include "base/macros.h" #include "mojo/application/public/cpp/interface_factory.h" +#include "mojo/application/public/interfaces/application_manager.mojom.h" #include "mojo/common/weak_binding_set.h" -#include "mojo/shell/application_manager.mojom.h" namespace mojo { namespace shell { @@ -36,7 +36,8 @@ // Overridden from mojom::ApplicationManager: void CreateInstanceForHandle(ScopedHandle channel, - const String& url) override; + const String& url, + CapabilityFilterPtr filter) override; mojo::shell::ApplicationManager* manager_;
diff --git a/net/cert/ct_known_logs.cc b/net/cert/ct_known_logs.cc index 1ff4bee..230450c 100644 --- a/net/cert/ct_known_logs.cc +++ b/net/cert/ct_known_logs.cc
@@ -28,8 +28,9 @@ } // namespace #if !defined(OS_NACL) -std::vector<scoped_refptr<CTLogVerifier>> CreateLogVerifiersForKnownLogs() { - std::vector<scoped_refptr<CTLogVerifier>> verifiers; +std::vector<scoped_refptr<const CTLogVerifier>> +CreateLogVerifiersForKnownLogs() { + std::vector<scoped_refptr<const CTLogVerifier>> verifiers; for (size_t i = 0; i < arraysize(kCTLogList); ++i) { const CTLogInfo& log(kCTLogList[i]); base::StringPiece key(log.log_key, log.log_key_length);
diff --git a/net/cert/ct_known_logs.h b/net/cert/ct_known_logs.h index c362aae..48904c2 100644 --- a/net/cert/ct_known_logs.h +++ b/net/cert/ct_known_logs.h
@@ -21,7 +21,7 @@ #if !defined(OS_NACL) // CreateLogVerifiersForKnownLogs returns a vector of CT logs for all the known // and trusted logs. -NET_EXPORT std::vector<scoped_refptr<CTLogVerifier>> +NET_EXPORT std::vector<scoped_refptr<const CTLogVerifier>> CreateLogVerifiersForKnownLogs(); #endif
diff --git a/net/cert/ct_log_verifier.cc b/net/cert/ct_log_verifier.cc index 7dbde12c..4f3bc83b 100644 --- a/net/cert/ct_log_verifier.cc +++ b/net/cert/ct_log_verifier.cc
@@ -11,7 +11,7 @@ namespace net { // static -scoped_refptr<CTLogVerifier> CTLogVerifier::Create( +scoped_refptr<const CTLogVerifier> CTLogVerifier::Create( const base::StringPiece& public_key, const base::StringPiece& description, const base::StringPiece& url) { @@ -35,7 +35,7 @@ } bool CTLogVerifier::Verify(const ct::LogEntry& entry, - const ct::SignedCertificateTimestamp& sct) { + const ct::SignedCertificateTimestamp& sct) const { if (sct.log_id != key_id()) { DVLOG(1) << "SCT is not signed by this log."; return false; @@ -60,7 +60,7 @@ } bool CTLogVerifier::VerifySignedTreeHead( - const ct::SignedTreeHead& signed_tree_head) { + const ct::SignedTreeHead& signed_tree_head) const { if (!SignatureParametersMatch(signed_tree_head.signature)) return false; @@ -74,7 +74,7 @@ } bool CTLogVerifier::SignatureParametersMatch( - const ct::DigitallySigned& signature) { + const ct::DigitallySigned& signature) const { if (!signature.SignatureParametersMatch(hash_algorithm_, signature_algorithm_)) { DVLOG(1) << "Mismatched hash or signature algorithm. Hash: "
diff --git a/net/cert/ct_log_verifier.h b/net/cert/ct_log_verifier.h index 0a9b3ef..5f2b090 100644 --- a/net/cert/ct_log_verifier.h +++ b/net/cert/ct_log_verifier.h
@@ -28,8 +28,12 @@ struct SignedTreeHead; } // namespace ct -// Class for verifying Signed Certificate Timestamps (SCTs) provided by a -// specific log (whose identity is provided during construction). +// Class for verifying signatures of a single Certificate Transparency +// log, whose identity is provided during construction. +// Currently can verify Signed Certificate Timestamp (SCT) and Signed +// Tree Head (STH) signatures. +// Immutable: Does not hold any state beyond the log information it was +// initialized with. class NET_EXPORT CTLogVerifier : public base::RefCountedThreadSafe<CTLogVerifier> { public: @@ -37,7 +41,7 @@ // using |public_key|, which is a DER-encoded SubjectPublicKeyInfo. // If |public_key| refers to an unsupported public key, returns NULL. // |description| is a textual description of the log. - static scoped_refptr<CTLogVerifier> Create( + static scoped_refptr<const CTLogVerifier> Create( const base::StringPiece& public_key, const base::StringPiece& description, const base::StringPiece& url); @@ -51,10 +55,10 @@ // Verifies that |sct| contains a valid signature for |entry|. bool Verify(const ct::LogEntry& entry, - const ct::SignedCertificateTimestamp& sct); + const ct::SignedCertificateTimestamp& sct) const; // Returns true if the signature in |signed_tree_head| verifies. - bool VerifySignedTreeHead(const ct::SignedTreeHead& signed_tree_head); + bool VerifySignedTreeHead(const ct::SignedTreeHead& signed_tree_head) const; private: FRIEND_TEST_ALL_PREFIXES(CTLogVerifierTest, VerifySignature); @@ -70,11 +74,11 @@ // that |signature| contains the raw signature data (eg: without any // DigitallySigned struct encoding). bool VerifySignature(const base::StringPiece& data_to_sign, - const base::StringPiece& signature); + const base::StringPiece& signature) const; // Returns true if the signature and hash algorithms in |signature| // match those of the log - bool SignatureParametersMatch(const ct::DigitallySigned& signature); + bool SignatureParametersMatch(const ct::DigitallySigned& signature) const; std::string key_id_; std::string description_;
diff --git a/net/cert/ct_log_verifier_nss.cc b/net/cert/ct_log_verifier_nss.cc index 75a87d61..fec7dc8 100644 --- a/net/cert/ct_log_verifier_nss.cc +++ b/net/cert/ct_log_verifier_nss.cc
@@ -117,7 +117,7 @@ } bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign, - const base::StringPiece& signature) { + const base::StringPiece& signature) const { SECItem sig_data; sig_data.data = reinterpret_cast<unsigned char*>(const_cast<char*>( signature.data()));
diff --git a/net/cert/ct_log_verifier_openssl.cc b/net/cert/ct_log_verifier_openssl.cc index af875a58..5fe41fd 100644 --- a/net/cert/ct_log_verifier_openssl.cc +++ b/net/cert/ct_log_verifier_openssl.cc
@@ -86,7 +86,7 @@ } bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign, - const base::StringPiece& signature) { + const base::StringPiece& signature) const { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_);
diff --git a/net/cert/ct_log_verifier_unittest.cc b/net/cert/ct_log_verifier_unittest.cc index 4f0fdcc..bc6e61cd 100644 --- a/net/cert/ct_log_verifier_unittest.cc +++ b/net/cert/ct_log_verifier_unittest.cc
@@ -27,7 +27,7 @@ } protected: - scoped_refptr<CTLogVerifier> log_; + scoped_refptr<const CTLogVerifier> log_; }; TEST_F(CTLogVerifierTest, VerifiesCertSCT) { @@ -95,7 +95,7 @@ std::string key = ct::GetTestPublicKey(); key += "extra"; - scoped_refptr<CTLogVerifier> log = + scoped_refptr<const CTLogVerifier> log = CTLogVerifier::Create(key, "testlog", "https://ct.example.com"); EXPECT_FALSE(log); }
diff --git a/net/cert/ct_objects_extractor_unittest.cc b/net/cert/ct_objects_extractor_unittest.cc index 7640e5bd..864686a 100644 --- a/net/cert/ct_objects_extractor_unittest.cc +++ b/net/cert/ct_objects_extractor_unittest.cc
@@ -52,7 +52,7 @@ protected: CertificateList precert_chain_; scoped_refptr<X509Certificate> test_cert_; - scoped_refptr<CTLogVerifier> log_; + scoped_refptr<const CTLogVerifier> log_; }; // Test that an SCT can be extracted and the extracted SCT contains the
diff --git a/net/cert/ct_verifier.h b/net/cert/ct_verifier.h index 40631048..46a811a 100644 --- a/net/cert/ct_verifier.h +++ b/net/cert/ct_verifier.h
@@ -21,6 +21,7 @@ class X509Certificate; // Interface for verifying Signed Certificate Timestamps over a certificate. +// The only known (non-test) implementation currently is MultiLogCTVerifier. class NET_EXPORT CTVerifier { public: class NET_EXPORT Observer { @@ -30,6 +31,8 @@ // Signed Certificate Timestamp, |cert| is the certificate it applies to. // The certificate is needed to calculate the hash of the log entry, // necessary for checking inclusion in the log. + // Note: The observer (whose implementation is expected to exist outside + // net/) may store the observed |cert| and |sct|. virtual void OnSCTVerified(X509Certificate* cert, const ct::SignedCertificateTimestamp* sct) = 0; };
diff --git a/net/cert/multi_log_ct_verifier.cc b/net/cert/multi_log_ct_verifier.cc index 7e421b2..d3ff737 100644 --- a/net/cert/multi_log_ct_verifier.cc +++ b/net/cert/multi_log_ct_verifier.cc
@@ -62,7 +62,7 @@ MultiLogCTVerifier::~MultiLogCTVerifier() { } void MultiLogCTVerifier::AddLogs( - const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers) { + const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers) { for (const auto& log_verifier : log_verifiers) { VLOG(1) << "Adding CT log: " << log_verifier->description(); logs_[log_verifier->key_id()] = log_verifier;
diff --git a/net/cert/multi_log_ct_verifier.h b/net/cert/multi_log_ct_verifier.h index 4546606..109d921 100644 --- a/net/cert/multi_log_ct_verifier.h +++ b/net/cert/multi_log_ct_verifier.h
@@ -23,15 +23,14 @@ // A Certificate Transparency verifier that can verify Signed Certificate // Timestamps from multiple logs. -// There should be a global instance of this class and for all known logs, -// AddLog should be called with a CTLogVerifier (which is created from the -// log's public key). +// It must be initialized with a list of logs by calling AddLogs. class NET_EXPORT MultiLogCTVerifier : public CTVerifier { public: MultiLogCTVerifier(); ~MultiLogCTVerifier() override; - void AddLogs(const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers); + void AddLogs( + const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers); // CTVerifier implementation: int Verify(X509Certificate* cert, @@ -61,7 +60,7 @@ // Mapping from a log's ID to the verifier for this log. // A log's ID is the SHA-256 of the log's key, as defined in section 3.2. // of RFC6962. - std::map<std::string, scoped_refptr<CTLogVerifier>> logs_; + std::map<std::string, scoped_refptr<const CTLogVerifier>> logs_; Observer* observer_;
diff --git a/net/cert/multi_log_ct_verifier_unittest.cc b/net/cert/multi_log_ct_verifier_unittest.cc index 492c21a..d5d609a 100644 --- a/net/cert/multi_log_ct_verifier_unittest.cc +++ b/net/cert/multi_log_ct_verifier_unittest.cc
@@ -50,7 +50,7 @@ class MultiLogCTVerifierTest : public ::testing::Test { public: void SetUp() override { - scoped_refptr<CTLogVerifier> log(CTLogVerifier::Create( + scoped_refptr<const CTLogVerifier> log(CTLogVerifier::Create( ct::GetTestPublicKey(), kLogDescription, "https://ct.example.com")); ASSERT_TRUE(log); log_verifiers_.push_back(log); @@ -206,7 +206,7 @@ scoped_ptr<MultiLogCTVerifier> verifier_; scoped_refptr<X509Certificate> chain_; scoped_refptr<X509Certificate> embedded_sct_chain_; - std::vector<scoped_refptr<CTLogVerifier>> log_verifiers_; + std::vector<scoped_refptr<const CTLogVerifier>> log_verifiers_; }; TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT) {
diff --git a/net/der/parse_values.h b/net/der/parse_values.h index d46fa803..a4ea8aa 100644 --- a/net/der/parse_values.h +++ b/net/der/parse_values.h
@@ -111,7 +111,7 @@ // Reads a DER-encoded ASN.1 GeneralizedTime value from |in| and puts the // resulting value in |out|, returning true if the GeneralizedTime could -// be parsed sucessfully. This function is even more restrictive than the +// be parsed successfully. This function is even more restrictive than the // DER rules - it follows the rules from RFC5280, which does not allow for // fractional seconds. NET_EXPORT bool ParseGeneralizedTime(const Input& in,
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index 8c19b9a5..38b100d 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc
@@ -2346,8 +2346,8 @@ cache_->clock_->Now()); if (validation_required_by_headers == VALIDATION_ASYNCHRONOUS) { - // Asynchronous revalidation is only supported for GET and HEAD methods. - if (request_->method != "GET" && request_->method != "HEAD") + // Asynchronous revalidation is only supported for GET methods. + if (request_->method != "GET") return VALIDATION_SYNCHRONOUS; }
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index adb4705..2a7e469c 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -333,7 +333,6 @@ void HttpNetworkSession::GetNpnProtos(NextProtoVector* npn_protos) const { if (HttpStreamFactory::spdy_enabled() && params_.enable_npn) { *npn_protos = next_protos_; - DisableHTTP2(npn_protos); } else { npn_protos->clear(); }
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index 6f8b203..32dd905 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h
@@ -116,6 +116,8 @@ FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, ResetStateForRestart); + FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, EnableNPN); + FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, DisableNPN); FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateReceived); FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest,
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 54c689b..b33d9ba 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -81,6 +81,7 @@ #include "net/ssl/ssl_private_key.h" #include "net/test/cert_test_util.h" #include "net/websockets/websocket_handshake_stream_base.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #include "url/gurl.h" @@ -15466,4 +15467,29 @@ trans->GetTotalReceivedBytes()); } +TEST_P(HttpNetworkTransactionTest, EnableNPN) { + session_deps_.next_protos = NextProtosDefaults(); + session_deps_.enable_npn = true; + + scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + + EXPECT_THAT(trans.server_ssl_config_.alpn_protos, + testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11)); + EXPECT_THAT(trans.server_ssl_config_.npn_protos, + testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11)); +} + +TEST_P(HttpNetworkTransactionTest, DisableNPN) { + session_deps_.next_protos = NextProtosDefaults(); + session_deps_.enable_npn = false; + + scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + + EXPECT_THAT(trans.server_ssl_config_.alpn_protos, + testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11)); + EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty()); +} + } // namespace net
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc index 6bd8230c..0bee91f 100644 --- a/net/http/http_transaction_test_util.cc +++ b/net/http/http_transaction_test_util.cc
@@ -244,6 +244,7 @@ received_bytes_(0), sent_bytes_(0), socket_log_id_(NetLog::Source::kInvalidId), + done_reading_called_(false), weak_factory_(this) {} MockNetworkTransaction::~MockNetworkTransaction() {} @@ -301,6 +302,7 @@ int MockNetworkTransaction::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { + CHECK(!done_reading_called_); 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) @@ -335,6 +337,8 @@ } void MockNetworkTransaction::DoneReading() { + CHECK(!done_reading_called_); + done_reading_called_ = true; if (transaction_factory_.get()) transaction_factory_->TransactionDoneReading(); } @@ -506,6 +510,7 @@ MockNetworkLayer::~MockNetworkLayer() {} void MockNetworkLayer::TransactionDoneReading() { + CHECK(!done_reading_called_); done_reading_called_ = true; }
diff --git a/net/http/http_transaction_test_util.h b/net/http/http_transaction_test_util.h index 34d8a25a..7744909 100644 --- a/net/http/http_transaction_test_util.h +++ b/net/http/http_transaction_test_util.h
@@ -268,6 +268,8 @@ // be initialized. unsigned int socket_log_id_; + bool done_reading_called_; + base::WeakPtrFactory<MockNetworkTransaction> weak_factory_; };
diff --git a/net/quic/congestion_control/tcp_cubic_bytes_sender.cc b/net/quic/congestion_control/tcp_cubic_bytes_sender.cc index c34d448..0dd8169 100644 --- a/net/quic/congestion_control/tcp_cubic_bytes_sender.cc +++ b/net/quic/congestion_control/tcp_cubic_bytes_sender.cc
@@ -295,12 +295,10 @@ QuicByteCount acked_bytes, QuicByteCount bytes_in_flight) { LOG_IF(DFATAL, InRecovery()) << "Never increase the CWND during recovery."; + // Do not increase the congestion window unless the sender is close to using + // the current window. if (!IsCwndLimited(bytes_in_flight)) { - // Do not increase the congestion window unless the sender is close to using - // the current window. - if (FLAGS_reset_cubic_epoch_when_app_limited) { - cubic_.OnApplicationLimited(); - } + cubic_.OnApplicationLimited(); return; } if (congestion_window_ >= max_congestion_window_) {
diff --git a/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc b/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc index d1f1403..70606dc 100644 --- a/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc +++ b/net/quic/congestion_control/tcp_cubic_bytes_sender_test.cc
@@ -402,7 +402,6 @@ } TEST_F(TcpCubicBytesSenderTest, TcpCubicResetEpochOnQuiescence) { - ValueRestore<bool> old_flag(&FLAGS_reset_cubic_epoch_when_app_limited, true); const int kMaxCongestionWindow = 50; const QuicByteCount kMaxCongestionWindowBytes = kMaxCongestionWindow * kDefaultTCPMSS;
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc index 81da996..0881981 100644 --- a/net/quic/congestion_control/tcp_cubic_sender.cc +++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -310,13 +310,10 @@ void TcpCubicSender::MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number, QuicByteCount bytes_in_flight) { LOG_IF(DFATAL, InRecovery()) << "Never increase the CWND during recovery."; + // Do not increase the congestion window unless the sender is close to using + // the current window. if (!IsCwndLimited(bytes_in_flight)) { - // Do not increase the congestion window unless the sender is close to using - // the current window. - if (FLAGS_reset_cubic_epoch_when_app_limited || - FLAGS_shift_quic_cubic_epoch_when_app_limited) { - cubic_.OnApplicationLimited(); - } + cubic_.OnApplicationLimited(); return; } if (congestion_window_ >= max_tcp_congestion_window_) {
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc index 3d13996..95fe69c 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -485,7 +485,6 @@ } TEST_F(TcpCubicSenderTest, TcpCubicResetEpochOnQuiescence) { - ValueRestore<bool> old_flag(&FLAGS_reset_cubic_epoch_when_app_limited, true); const int kMaxCongestionWindow = 50; const QuicByteCount kMaxCongestionWindowBytes = kMaxCongestionWindow * kDefaultTCPMSS;
diff --git a/net/quic/p2p/quic_p2p_stream.cc b/net/quic/p2p/quic_p2p_stream.cc index af31f3c..a8e00c6 100644 --- a/net/quic/p2p/quic_p2p_stream.cc +++ b/net/quic/p2p/quic_p2p_stream.cc
@@ -49,7 +49,7 @@ } } -QuicPriority QuicP2PStream::EffectivePriority() const { +SpdyPriority QuicP2PStream::Priority() const { return priority_; }
diff --git a/net/quic/p2p/quic_p2p_stream.h b/net/quic/p2p/quic_p2p_stream.h index 5a1abccc..aea66f3 100644 --- a/net/quic/p2p/quic_p2p_stream.h +++ b/net/quic/p2p/quic_p2p_stream.h
@@ -40,7 +40,7 @@ void OnDataAvailable() override; void OnClose() override; void OnCanWrite() override; - QuicPriority EffectivePriority() const override; + SpdyPriority Priority() const override; void WriteHeader(base::StringPiece data); @@ -52,7 +52,7 @@ private: Delegate* delegate_ = nullptr; - QuicPriority priority_ = 0; + SpdyPriority priority_ = 0; CompletionCallback write_callback_; int last_write_size_ = 0;
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index 79d5131..8589f20 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc
@@ -737,6 +737,9 @@ return false; } + if (FLAGS_quic_respect_send_alarm && send_alarm_->IsSet()) { + send_alarm_->Cancel(); + } ProcessAckFrame(incoming_ack); if (incoming_ack.is_truncated) { should_last_packet_instigate_acks_ = true; @@ -1475,7 +1478,7 @@ } // If the send alarm is set, wait for it to fire. - if (FLAGS_respect_send_alarm && send_alarm_->IsSet()) { + if (FLAGS_quic_respect_send_alarm && send_alarm_->IsSet()) { return false; } @@ -1494,7 +1497,7 @@ << "ms"; return false; } - if (!FLAGS_respect_send_alarm) { + if (!FLAGS_quic_respect_send_alarm) { send_alarm_->Cancel(); } return true;
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h index 45b079c..488950ef 100644 --- a/net/quic/quic_connection.h +++ b/net/quic/quic_connection.h
@@ -32,7 +32,8 @@ #include "net/quic/crypto/quic_decrypter.h" #include "net/quic/quic_alarm.h" #include "net/quic/quic_blocked_writer_interface.h" -#include "net/quic/quic_connection_stats.h" +#include "net/quic/quic_fec_group.h" +#include "net/quic/quic_framer.h" #include "net/quic/quic_packet_creator.h" #include "net/quic/quic_packet_generator.h" #include "net/quic/quic_packet_writer.h" @@ -48,7 +49,6 @@ class QuicClock; class QuicConfig; class QuicConnection; -class QuicDecrypter; class QuicEncrypter; class QuicFecGroup; class QuicRandom;
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index 15dd943..c503b5157 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc
@@ -676,7 +676,10 @@ framer_(SupportedVersions(version()), QuicTime::Zero(), Perspective::IS_CLIENT), - peer_creator_(connection_id_, &framer_, &random_generator_), + peer_creator_(connection_id_, + &framer_, + &random_generator_, + /*delegate=*/nullptr), send_algorithm_(new StrictMock<MockSendAlgorithm>), loss_algorithm_(new MockLossAlgorithm()), helper_(new TestConnectionHelper(&clock_, &random_generator_)), @@ -5249,6 +5252,36 @@ connection_.SendGoAway(QUIC_PEER_GOING_AWAY, kHeadersStreamId, "Going Away."); } +TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) { + FLAGS_quic_respect_send_alarm = true; + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + nullptr); + + // Evaluate CanWrite, and have it return a non-Zero value. + EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)) + .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1))); + connection_.OnCanWrite(); + EXPECT_TRUE(connection_.GetSendAlarm()->IsSet()); + EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(1)), + connection_.GetSendAlarm()->deadline()); + + // Process an ack and the send alarm will be set to the new 2ms delay. + QuicAckFrame ack = InitAckFrame(1); + EXPECT_CALL(*loss_algorithm_, DetectLostPackets(_, _, _, _)) + .WillOnce(Return(PacketNumberSet())); + EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _)); + EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _)) + .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(2))); + ProcessAckPacket(&ack); + EXPECT_EQ(1u, writer_->frame_count()); + EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_TRUE(connection_.GetSendAlarm()->IsSet()); + EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(2)), + connection_.GetSendAlarm()->deadline()); + writer_->Reset(); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/quic_crypto_stream.cc b/net/quic/quic_crypto_stream.cc index 07787608..fdee373 100644 --- a/net/quic/quic_crypto_stream.cc +++ b/net/quic/quic_crypto_stream.cc
@@ -15,6 +15,7 @@ using std::string; using base::StringPiece; +using net::SpdyPriority; namespace net { @@ -58,8 +59,8 @@ } } -QuicPriority QuicCryptoStream::EffectivePriority() const { - return QuicUtils::HighestPriority(); +SpdyPriority QuicCryptoStream::Priority() const { + return net::kHighestPriority; // The smallest priority is also the highest } void QuicCryptoStream::SendHandshakeMessage(
diff --git a/net/quic/quic_crypto_stream.h b/net/quic/quic_crypto_stream.h index 33268a9..de88dc2 100644 --- a/net/quic/quic_crypto_stream.h +++ b/net/quic/quic_crypto_stream.h
@@ -39,7 +39,7 @@ // ReliableQuicStream implementation void OnDataAvailable() override; - QuicPriority EffectivePriority() const override; + SpdyPriority Priority() const override; // Sends |message| to the peer. // TODO(wtc): return a success/failure status.
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc index 0c9baed..5ecec05a 100644 --- a/net/quic/quic_flags.cc +++ b/net/quic/quic_flags.cc
@@ -58,10 +58,6 @@ // client, a GO_AWAY frame is sent to the client. bool FLAGS_send_goaway_after_client_migration = true; -// QUIC-specific flag. If true, Cubic's epoch is reset when the sender is -// application-limited. -bool FLAGS_reset_cubic_epoch_when_app_limited = true; - // If true, use an interval set as the internal representation of a packet queue // instead of a set. bool FLAGS_quic_packet_queue_use_interval_set = true; @@ -73,11 +69,6 @@ // quota from open streams, which is 10 times larger. bool FLAGS_allow_many_available_streams = true; -// If true, QuicPacketReader::ReadAndDispatchPackets will only return true if -// recvmmsg fills all of the passed in messages. Otherwise, it will return true -// if recvmmsg read any messages. -bool FLAGS_quic_read_packets_full_recvmmsg = true; - // If true, QUIC will measure head of line (HOL) blocking due between // streams due to packet losses on the headers stream. The // measurements will be surfaced via UMA histogram @@ -100,11 +91,6 @@ // and AckNotifierManager. bool FLAGS_quic_no_ack_notifier = true; -// If true, QuicSession::GetNumOpenStreams will count unfinished -// streams as open streams, QuicSession::PostProcessAfterData will not -// check the quota of unifinished streams. -bool FLAGS_quic_count_unfinished_as_open_streams = true; - // If true, use the unrolled prefetch path in QuicPacketCreator::CopyToBuffer. bool FLAGS_quic_packet_creator_prefetch = false; @@ -121,5 +107,8 @@ bool FLAGS_quic_use_stream_sequencer_buffer = true; // If true, don't send QUIC packets if the send alarm is set. -// Disabled until b/25638635 is resolved. -bool FLAGS_respect_send_alarm = false; +bool FLAGS_quic_respect_send_alarm = true; + +// If true, allow each quic stream to write 16k blocks rather than doing a round +// robin of one packet per session when ack clocked or paced. +bool FLAGS_quic_batch_writes = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h index 5cf76499..bc931048 100644 --- a/net/quic/quic_flags.h +++ b/net/quic/quic_flags.h
@@ -22,20 +22,18 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_limit_max_cwnd; NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_handshake_confirmation; NET_EXPORT_PRIVATE extern bool FLAGS_send_goaway_after_client_migration; -NET_EXPORT_PRIVATE extern bool FLAGS_reset_cubic_epoch_when_app_limited; NET_EXPORT_PRIVATE extern bool FLAGS_quic_packet_queue_use_interval_set; NET_EXPORT_PRIVATE extern bool FLAGS_shift_quic_cubic_epoch_when_app_limited; NET_EXPORT_PRIVATE extern bool FLAGS_allow_many_available_streams; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_read_packets_full_recvmmsg; NET_EXPORT_PRIVATE extern bool FLAGS_quic_measure_headers_hol_blocking_time; NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_pacing; NET_EXPORT_PRIVATE extern bool FLAGS_quic_fix_fin_accounting; NET_EXPORT_PRIVATE extern bool FLAGS_quic_implement_stop_reading; NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_ack_notifier; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_count_unfinished_as_open_streams; NET_EXPORT_PRIVATE extern bool FLAGS_quic_packet_creator_prefetch; NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_non_nat_address_migration; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_new_idle_timeout; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_stream_sequencer_buffer; -NET_EXPORT_PRIVATE extern bool FLAGS_respect_send_alarm; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_respect_send_alarm; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_batch_writes; #endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc index 45b9c67..eceb6cc 100644 --- a/net/quic/quic_framer.cc +++ b/net/quic/quic_framer.cc
@@ -160,18 +160,18 @@ QuicStreamOffset offset, bool last_frame_in_packet, InFecGroup is_in_fec_group) { - bool no_stream_frame_length = last_frame_in_packet && - is_in_fec_group == NOT_IN_FEC_GROUP; + bool no_stream_frame_length = + last_frame_in_packet && is_in_fec_group == NOT_IN_FEC_GROUP; return kQuicFrameTypeSize + GetStreamIdSize(stream_id) + - GetStreamOffsetSize(offset) + - (no_stream_frame_length ? 0 : kQuicStreamPayloadLengthSize); + GetStreamOffsetSize(offset) + + (no_stream_frame_length ? 0 : kQuicStreamPayloadLengthSize); } // static size_t QuicFramer::GetMinAckFrameSize( QuicPacketNumberLength largest_observed_length) { - return kQuicFrameTypeSize + kQuicEntropyHashSize + - largest_observed_length + kQuicDeltaTimeLargestObservedSize; + return kQuicFrameTypeSize + kQuicEntropyHashSize + largest_observed_length + + kQuicDeltaTimeLargestObservedSize; } // static @@ -182,9 +182,8 @@ // static size_t QuicFramer::GetMinRstStreamFrameSize() { - return kQuicFrameTypeSize + kQuicMaxStreamIdSize + - kQuicMaxStreamOffsetSize + kQuicErrorCodeSize + - kQuicErrorDetailsLengthSize; + return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize + + kQuicErrorCodeSize + kQuicErrorDetailsLengthSize; } // static @@ -201,7 +200,7 @@ // static size_t QuicFramer::GetMinGoAwayFrameSize() { return kQuicFrameTypeSize + kQuicErrorCodeSize + kQuicErrorDetailsLengthSize + - kQuicMaxStreamIdSize; + kQuicMaxStreamIdSize; } // static @@ -248,7 +247,7 @@ // static size_t QuicFramer::GetVersionNegotiationPacketSize(size_t number_versions) { return kPublicFlagsSize + PACKET_8BYTE_CONNECTION_ID + - number_versions * kQuicVersionSize; + number_versions * kQuicVersionSize; } bool QuicFramer::IsSupportedVersion(const QuicVersion version) const { @@ -343,22 +342,21 @@ writer.WritePadding(); break; case STREAM_FRAME: - if (!AppendStreamFrame( - *frame.stream_frame, no_stream_frame_length, &writer)) { + if (!AppendStreamFrame(*frame.stream_frame, no_stream_frame_length, + &writer)) { LOG(DFATAL) << "AppendStreamFrame failed"; return 0; } break; case ACK_FRAME: - if (!AppendAckFrameAndTypeByte( - header, *frame.ack_frame, &writer)) { + if (!AppendAckFrameAndTypeByte(header, *frame.ack_frame, &writer)) { LOG(DFATAL) << "AppendAckFrameAndTypeByte failed"; return 0; } break; case STOP_WAITING_FRAME: - if (!AppendStopWaitingFrame( - header, *frame.stop_waiting_frame, &writer)) { + if (!AppendStopWaitingFrame(header, *frame.stop_waiting_frame, + &writer)) { LOG(DFATAL) << "AppendStopWaitingFrame failed"; return 0; } @@ -375,8 +373,8 @@ } break; case CONNECTION_CLOSE_FRAME: - if (!AppendConnectionCloseFrame( - *frame.connection_close_frame, &writer)) { + if (!AppendConnectionCloseFrame(*frame.connection_close_frame, + &writer)) { LOG(DFATAL) << "AppendConnectionCloseFrame failed"; return 0; } @@ -659,8 +657,8 @@ if (reset->GetStringPiece(kCADR, &address)) { QuicSocketAddressCoder address_coder; if (address_coder.Decode(address.data(), address.length())) { - packet.client_address = IPEndPoint(address_coder.ip(), - address_coder.port()); + packet.client_address = + IPEndPoint(address_coder.ip(), address_coder.port()); } } @@ -712,34 +710,34 @@ switch (header.public_header.connection_id_length) { case PACKET_0BYTE_CONNECTION_ID: - if (!writer->WriteUInt8( - public_flags | PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID)) { + if (!writer->WriteUInt8(public_flags | + PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID)) { return false; } break; case PACKET_1BYTE_CONNECTION_ID: - if (!writer->WriteUInt8( - public_flags | PACKET_PUBLIC_FLAGS_1BYTE_CONNECTION_ID)) { - return false; + if (!writer->WriteUInt8(public_flags | + PACKET_PUBLIC_FLAGS_1BYTE_CONNECTION_ID)) { + return false; } - if (!writer->WriteUInt8( - header.public_header.connection_id & k1ByteConnectionIdMask)) { + if (!writer->WriteUInt8(header.public_header.connection_id & + k1ByteConnectionIdMask)) { return false; } break; case PACKET_4BYTE_CONNECTION_ID: - if (!writer->WriteUInt8( - public_flags | PACKET_PUBLIC_FLAGS_4BYTE_CONNECTION_ID)) { - return false; + if (!writer->WriteUInt8(public_flags | + PACKET_PUBLIC_FLAGS_4BYTE_CONNECTION_ID)) { + return false; } - if (!writer->WriteUInt32( - header.public_header.connection_id & k4ByteConnectionIdMask)) { + if (!writer->WriteUInt32(header.public_header.connection_id & + k4ByteConnectionIdMask)) { return false; } break; case PACKET_8BYTE_CONNECTION_ID: - if (!writer->WriteUInt8( - public_flags | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID)) { + if (!writer->WriteUInt8(public_flags | + PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID)) { return false; } if (!writer->WriteUInt64(header.public_header.connection_id)) { @@ -808,11 +806,10 @@ uint64 prev_epoch = epoch - epoch_delta; uint64 next_epoch = epoch + epoch_delta; - uint64 time = ClosestTo(last_timestamp_.ToMicroseconds(), - epoch + time_delta_us, - ClosestTo(last_timestamp_.ToMicroseconds(), - prev_epoch + time_delta_us, - next_epoch + time_delta_us)); + uint64 time = ClosestTo( + last_timestamp_.ToMicroseconds(), epoch + time_delta_us, + ClosestTo(last_timestamp_.ToMicroseconds(), prev_epoch + time_delta_us, + next_epoch + time_delta_us)); return QuicTime::Delta::FromMicroseconds(time); } @@ -852,8 +849,8 @@ public_header->version_flag = (public_flags & PACKET_PUBLIC_FLAGS_VERSION) != 0; - if (validate_flags_ && - !public_header->version_flag && public_flags > PACKET_PUBLIC_FLAGS_MAX) { + if (validate_flags_ && !public_header->version_flag && + public_flags > PACKET_PUBLIC_FLAGS_MAX) { set_detailed_error("Illegal public flags value."); return false; } @@ -881,9 +878,10 @@ } if (last_serialized_connection_id_ && (public_header->connection_id & k4ByteConnectionIdMask) != - (last_serialized_connection_id_ & k4ByteConnectionIdMask)) { - set_detailed_error("Truncated 4 byte ConnectionId does not match " - "previous connection_id."); + (last_serialized_connection_id_ & k4ByteConnectionIdMask)) { + set_detailed_error( + "Truncated 4 byte ConnectionId does not match " + "previous connection_id."); return false; } public_header->connection_id_length = PACKET_4BYTE_CONNECTION_ID; @@ -897,9 +895,10 @@ } if (last_serialized_connection_id_ && (public_header->connection_id & k1ByteConnectionIdMask) != - (last_serialized_connection_id_ & k1ByteConnectionIdMask)) { - set_detailed_error("Truncated 1 byte ConnectionId does not match " - "previous connection_id."); + (last_serialized_connection_id_ & k1ByteConnectionIdMask)) { + set_detailed_error( + "Truncated 1 byte ConnectionId does not match " + "previous connection_id."); return false; } public_header->connection_id_length = PACKET_1BYTE_CONNECTION_ID; @@ -1124,8 +1123,7 @@ // This was a special frame type that did not match any // of the known ones. Error. set_detailed_error("Illegal frame type."); - DLOG(WARNING) << "Illegal frame type: " - << static_cast<int>(frame_type); + DLOG(WARNING) << "Illegal frame type: " << static_cast<int>(frame_type); return RaiseError(QUIC_INVALID_FRAME_DATA); } @@ -1225,8 +1223,7 @@ default: set_detailed_error("Illegal frame type."); - DLOG(WARNING) << "Illegal frame type: " - << static_cast<int>(frame_type); + DLOG(WARNING) << "Illegal frame type: " << static_cast<int>(frame_type); return RaiseError(QUIC_INVALID_FRAME_DATA); } } @@ -1604,8 +1601,7 @@ return alternative_decrypter_.get(); } -void QuicFramer::SetEncrypter(EncryptionLevel level, - QuicEncrypter* encrypter) { +void QuicFramer::SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter) { DCHECK_GE(level, 0); DCHECK_LT(level, NUM_ENCRYPTION_LEVELS); encrypter_[level].reset(encrypter); @@ -1711,7 +1707,7 @@ size_t ack_size = GetMinAckFrameSize(largest_observed_length); if (!ack_info.nack_ranges.empty()) { - ack_size += kNumberOfNackRangesSize + kNumberOfRevivedPacketsSize; + ack_size += kNumberOfNackRangesSize + kNumberOfRevivedPacketsSize; ack_size += min(ack_info.nack_ranges.size(), kMaxNackRanges) * (missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER); if (ack.latest_revived_packet != 0) { @@ -1763,7 +1759,7 @@ return GetRstStreamFrameSize(); case CONNECTION_CLOSE_FRAME: return GetMinConnectionCloseFrameSize() + - frame.connection_close_frame->error_details.size(); + frame.connection_close_frame->error_details.size(); case GOAWAY_FRAME: return GetMinGoAwayFrameSize() + frame.goaway_frame->reason_phrase.size(); case WINDOW_UPDATE_FRAME: @@ -1797,7 +1793,7 @@ // Data Length bit. type_byte <<= kQuicStreamDataLengthShift; - type_byte |= no_stream_frame_length ? 0: kQuicStreamDataLengthMask; + type_byte |= no_stream_frame_length ? 0 : kQuicStreamDataLengthMask; // Offset 3 bits. type_byte <<= kQuicStreamOffsetShift; @@ -1854,10 +1850,9 @@ } } -bool QuicFramer::AppendStreamFrame( - const QuicStreamFrame& frame, - bool no_stream_frame_length, - QuicDataWriter* writer) { +bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame, + bool no_stream_frame_length, + QuicDataWriter* writer) { if (!writer->WriteBytes(&frame.stream_id, GetStreamIdSize(frame.stream_id))) { LOG(DFATAL) << "Writing stream id size failed."; return false; @@ -1886,10 +1881,9 @@ quic_version_ = version; } -bool QuicFramer::AppendAckFrameAndTypeByte( - const QuicPacketHeader& header, - const QuicAckFrame& frame, - QuicDataWriter* writer) { +bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header, + const QuicAckFrame& frame, + QuicDataWriter* writer) { AckFrameInfo ack_info = GetAckFrameInfo(frame); QuicPacketNumber ack_largest_observed = frame.largest_observed; QuicPacketNumberLength largest_observed_length = @@ -1953,8 +1947,8 @@ return false; } - if (!AppendPacketSequenceNumber(largest_observed_length, - ack_largest_observed, writer)) { + if (!AppendPacketSequenceNumber(largest_observed_length, ack_largest_observed, + writer)) { return false; } @@ -2055,16 +2049,16 @@ return false; } - if (!writer->WriteUInt8( - delta_from_largest_observed & k1ByteSequenceNumberMask)) { + if (!writer->WriteUInt8(delta_from_largest_observed & + k1ByteSequenceNumberMask)) { return false; } // Use the lowest 4 bytes of the time delta from the creation_time_. const uint64 time_epoch_delta_us = UINT64_C(1) << 32; uint32 time_delta_us = - static_cast<uint32>(it->second.Subtract(creation_time_).ToMicroseconds() - & (time_epoch_delta_us - 1)); + static_cast<uint32>(it->second.Subtract(creation_time_).ToMicroseconds() & + (time_epoch_delta_us - 1)); if (!writer->WriteBytes(&time_delta_us, sizeof(time_delta_us))) { return false; } @@ -2079,8 +2073,8 @@ return false; } - if (!writer->WriteUInt8( - delta_from_largest_observed & k1ByteSequenceNumberMask)) { + if (!writer->WriteUInt8(delta_from_largest_observed & + k1ByteSequenceNumberMask)) { return false; } @@ -2094,10 +2088,9 @@ return true; } -bool QuicFramer::AppendStopWaitingFrame( - const QuicPacketHeader& header, - const QuicStopWaitingFrame& frame, - QuicDataWriter* writer) { +bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header, + const QuicStopWaitingFrame& frame, + QuicDataWriter* writer) { DCHECK_GE(header.packet_number, frame.least_unacked); const QuicPacketNumber least_unacked_delta = header.packet_number - frame.least_unacked;
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h index 53ca193..62f2ece 100644 --- a/net/quic/quic_framer.h +++ b/net/quic/quic_framer.h
@@ -51,13 +51,11 @@ // Size in bytes reserved for the number of missing packets in ack frames. const size_t kNumberOfNackRangesSize = 1; // Maximum number of missing packet ranges that can fit within an ack frame. -const size_t kMaxNackRanges = - (1 << (kNumberOfNackRangesSize * 8)) - 1; +const size_t kMaxNackRanges = (1 << (kNumberOfNackRangesSize * 8)) - 1; // Size in bytes reserved for the number of revived packets in ack frames. const size_t kNumberOfRevivedPacketsSize = 1; // Maximum number of revived packets that can fit within an ack frame. -const size_t kMaxRevivedPackets = - (1 << (kNumberOfRevivedPacketsSize * 8)) - 1; +const size_t kMaxRevivedPackets = (1 << (kNumberOfRevivedPacketsSize * 8)) - 1; // This class receives callbacks from the framer when packets // are processed. @@ -81,8 +79,7 @@ // Called when a public reset packet has been parsed but has not yet // been validated. - virtual void OnPublicResetPacket( - const QuicPublicResetPacket& packet) = 0; + virtual void OnPublicResetPacket(const QuicPublicResetPacket& packet) = 0; // Called only when |perspective_| is IS_CLIENT and a version negotiation // packet has been parsed. @@ -189,17 +186,13 @@ // else the framer will likely crash. It is acceptable for the visitor // to do nothing. If this is called multiple times, only the last visitor // will be used. - void set_visitor(QuicFramerVisitorInterface* visitor) { - visitor_ = visitor; - } + void set_visitor(QuicFramerVisitorInterface* visitor) { visitor_ = visitor; } const QuicVersionVector& supported_versions() const { return supported_versions_; } - QuicVersion version() const { - return quic_version_; - } + QuicVersion version() const { return quic_version_; } void set_version(const QuicVersion version); @@ -218,9 +211,7 @@ entropy_calculator_ = entropy_calculator; } - QuicErrorCode error() const { - return error_; - } + QuicErrorCode error() const { return error_; } // Pass a UDP packet into the framer for parsing. // Return true if the packet was processed succesfully. |packet| must be a @@ -496,13 +487,9 @@ bool RaiseError(QuicErrorCode error); - void set_error(QuicErrorCode error) { - error_ = error; - } + void set_error(QuicErrorCode error) { error_ = error; } - void set_detailed_error(const char* error) { - detailed_error_ = error; - } + void set_detailed_error(const char* error) { detailed_error_ = error; } std::string detailed_error_; QuicFramerVisitorInterface* visitor_;
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index 4e284a4..e621c0d 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc
@@ -66,7 +66,7 @@ size_t GetPacketNumberOffset(QuicConnectionIdLength connection_id_length, bool include_version) { return kConnectionIdOffset + connection_id_length + - (include_version ? kQuicVersionSize : 0); + (include_version ? kQuicVersionSize : 0); } size_t GetPacketNumberOffset(bool include_version) { @@ -94,12 +94,12 @@ size_t GetFecGroupOffset(QuicConnectionIdLength connection_id_length, bool include_version) { return GetPrivateFlagsOffset(connection_id_length, include_version) + - kPrivateFlagsSize; + kPrivateFlagsSize; } size_t GetFecGroupOffset(bool include_version) { return GetPrivateFlagsOffset(PACKET_8BYTE_CONNECTION_ID, include_version) + - kPrivateFlagsSize; + kPrivateFlagsSize; } size_t GetFecGroupOffset(bool include_version, @@ -185,8 +185,7 @@ complete_packets_(0), revived_packets_(0), accept_packet_(true), - accept_public_header_(true) { - } + accept_public_header_(true) {} ~TestQuicVisitor() override { STLDeleteElements(&stream_frames_); @@ -353,13 +352,13 @@ // Helper function to get unsigned char representation of digit in the // units place of the current QUIC version number. unsigned char GetQuicVersionDigitOnes() { - return static_cast<unsigned char> ('0' + version_%10); + return static_cast<unsigned char>('0' + version_ % 10); } // Helper function to get unsigned char representation of digit in the // tens place of the current QUIC version number. unsigned char GetQuicVersionDigitTens() { - return static_cast<unsigned char> ('0' + (version_/10)%10); + return static_cast<unsigned char>('0' + (version_ / 10) % 10); } bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) { @@ -370,14 +369,14 @@ } if (packet->AssociatedData() != encrypter_->associated_data_) { LOG(ERROR) << "Encrypted incorrect associated data. expected " - << packet->AssociatedData() << " actual: " - << encrypter_->associated_data_; + << packet->AssociatedData() + << " actual: " << encrypter_->associated_data_; return false; } if (packet->Plaintext() != encrypter_->plaintext_) { LOG(ERROR) << "Encrypted incorrect plaintext data. expected " - << packet->Plaintext() << " actual: " - << encrypter_->plaintext_; + << packet->Plaintext() + << " actual: " << encrypter_->plaintext_; return false; } return true; @@ -406,16 +405,13 @@ PACKET_6BYTE_PACKET_NUMBER))); if (ciphertext != decrypter_->ciphertext_) { LOG(ERROR) << "Decrypted incorrect ciphertext data. expected " - << ciphertext << " actual: " - << decrypter_->ciphertext_; + << ciphertext << " actual: " << decrypter_->ciphertext_; return false; } return true; } - char* AsChars(unsigned char* data) { - return reinterpret_cast<char*>(data); - } + char* AsChars(unsigned char* data) { return reinterpret_cast<char*>(data); } void CheckProcessingFails(unsigned char* packet, size_t len, @@ -592,7 +588,7 @@ } TEST_P(QuicFramerTest, EmptyPacket) { - char packet[] = { 0x00 }; + char packet[] = {0x00}; QuicEncryptedPacket encrypted(packet, 0, false); EXPECT_FALSE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error()); @@ -1071,9 +1067,7 @@ }; // clang-format on - CheckProcessingFails(packet, - arraysize(packet), - "Illegal public flags value.", + CheckProcessingFails(packet, arraysize(packet), "Illegal public flags value.", QUIC_INVALID_PACKET_HEADER); // Now turn off validation. @@ -1103,9 +1097,7 @@ 0x00, 0x00, 0x00, 0x00 }; // clang-format on - CheckProcessingFails(packet, - arraysize(packet), - "Illegal public flags value.", + CheckProcessingFails(packet, arraysize(packet), "Illegal public flags value.", QUIC_INVALID_PACKET_HEADER); }; @@ -1157,8 +1149,7 @@ 0x00, 0x00, 0x00, 0x00 }; // clang-format on - CheckProcessingFails(packet, - arraysize(packet), + CheckProcessingFails(packet, arraysize(packet), "Illegal private flags value.", QUIC_INVALID_PACKET_HEADER); }; @@ -1577,9 +1568,8 @@ header.fec_group = 0; // Do not encrypt the payload because the revived payload is post-encryption. - EXPECT_TRUE(framer_.ProcessRevivedPacket(&header, - StringPiece(AsChars(payload), - arraysize(payload)))); + EXPECT_TRUE(framer_.ProcessRevivedPacket( + &header, StringPiece(AsChars(payload), arraysize(payload)))); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); ASSERT_EQ(1, visitor_.revived_packets_); @@ -1715,8 +1705,8 @@ EXPECT_EQ(kMissingPacket, frame.missing_packets.Min()); const size_t kReceivedEntropyOffset = kQuicFrameTypeSize; - const size_t kLargestObservedOffset = kReceivedEntropyOffset + - kQuicEntropyHashSize; + const size_t kLargestObservedOffset = + kReceivedEntropyOffset + kQuicEntropyHashSize; const size_t kMissingDeltaTimeOffset = kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER; const size_t kNumTimestampsOffset = @@ -1840,7 +1830,7 @@ const size_t kTimestampDeltaLargestObserved = kNumTimestampsOffset + kQuicNumTimestampsSize; const size_t kTimestampTimeDeltaLargestObserved = - kTimestampDeltaLargestObserved + 1; + kTimestampDeltaLargestObserved + 1; const size_t kNumMissingPacketOffset = kTimestampTimeDeltaLargestObserved + 4; const size_t kMissingPacketsOffset = kNumMissingPacketOffset + kNumberOfNackRangesSize; @@ -1932,16 +1922,16 @@ EXPECT_EQ(kMissingPacket, frame.missing_packets.Min()); const size_t kReceivedEntropyOffset = kQuicFrameTypeSize; - const size_t kLargestObservedOffset = kReceivedEntropyOffset + - kQuicEntropyHashSize; + const size_t kLargestObservedOffset = + kReceivedEntropyOffset + kQuicEntropyHashSize; const size_t kMissingDeltaTimeOffset = kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER; - const size_t kNumTimestampsOffset = kMissingDeltaTimeOffset + - kQuicDeltaTimeLargestObservedSize; - const size_t kNumMissingPacketOffset = kNumTimestampsOffset + - kQuicNumTimestampsSize; - const size_t kMissingPacketsOffset = kNumMissingPacketOffset + - kNumberOfNackRangesSize; + const size_t kNumTimestampsOffset = + kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize; + const size_t kNumMissingPacketOffset = + kNumTimestampsOffset + kQuicNumTimestampsSize; + const size_t kMissingPacketsOffset = + kNumMissingPacketOffset + kNumberOfNackRangesSize; const size_t kMissingPacketsRange = kMissingPacketsOffset + PACKET_1BYTE_PACKET_NUMBER; const size_t kRevivedPacketsLength = @@ -2030,16 +2020,16 @@ EXPECT_EQ(kMissingPacket, frame.missing_packets.Min()); const size_t kReceivedEntropyOffset = kQuicFrameTypeSize; - const size_t kLargestObservedOffset = kReceivedEntropyOffset + - kQuicEntropyHashSize; + const size_t kLargestObservedOffset = + kReceivedEntropyOffset + kQuicEntropyHashSize; const size_t kMissingDeltaTimeOffset = kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER; - const size_t kNumTimestampsOffset = kMissingDeltaTimeOffset + - kQuicDeltaTimeLargestObservedSize; - const size_t kNumMissingPacketOffset = kNumTimestampsOffset + - kQuicNumTimestampsSize; - const size_t kMissingPacketsOffset = kNumMissingPacketOffset + - kNumberOfNackRangesSize; + const size_t kNumTimestampsOffset = + kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize; + const size_t kNumMissingPacketOffset = + kNumTimestampsOffset + kQuicNumTimestampsSize; + const size_t kMissingPacketsOffset = + kNumMissingPacketOffset + kNumberOfNackRangesSize; const size_t kMissingPacketsRange = kMissingPacketsOffset + PACKET_1BYTE_PACKET_NUMBER; const size_t kRevivedPacketsLength = @@ -2194,9 +2184,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, StopWaitingFrame) { @@ -2423,8 +2413,8 @@ string expected_error; if (i < kQuicFrameTypeSize + kQuicErrorCodeSize) { expected_error = "Unable to read go away error code."; - } else if (i < kQuicFrameTypeSize + kQuicErrorCodeSize + - kQuicMaxStreamIdSize) { + } else if (i < + kQuicFrameTypeSize + kQuicErrorCodeSize + kQuicMaxStreamIdSize) { expected_error = "Unable to read last good stream id."; } else { expected_error = "Unable to read goaway reason."; @@ -2603,8 +2593,8 @@ EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof); EXPECT_EQ(kPacketNumber, visitor_.public_reset_packet_->rejected_packet_number); - EXPECT_TRUE( - visitor_.public_reset_packet_->client_address.address().empty()); + EXPECT_EQ(ADDRESS_FAMILY_UNSPECIFIED, + visitor_.public_reset_packet_->client_address.GetFamily()); // Now test framing boundaries. for (size_t i = 0; i < arraysize(packet); ++i) { @@ -2852,9 +2842,8 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), arraysize(packet)); } @@ -2900,9 +2889,8 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), arraysize(packet)); } @@ -2948,9 +2936,8 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), arraysize(packet)); } @@ -2996,9 +2983,8 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), arraysize(packet)); } @@ -3048,9 +3034,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildStreamFramePacketInFecGroup) { @@ -3097,9 +3083,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) { @@ -3123,58 +3109,22 @@ // public flags (version, 8 byte connection_id) 0x3D, // connection_id - 0x10, - 0x32, - 0x54, - 0x76, - 0x98, - 0xBA, - 0xDC, - 0xFE, + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag - 'Q', - '0', - GetQuicVersionDigitTens(), - GetQuicVersionDigitOnes(), + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), // packet number - 0xBC, - 0x9A, - 0x78, - 0x56, - 0x34, - 0x12, + 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, // private flags (entropy) 0x01, // frame type (stream frame with fin and no length) 0xDF, // stream id - 0x04, - 0x03, - 0x02, - 0x01, + 0x04, 0x03, 0x02, 0x01, // offset - 0x54, - 0x76, - 0x10, - 0x32, - 0xDC, - 0xFE, - 0x98, - 0xBA, + 0x54, 0x76, 0x10, 0x32, 0xDC, 0xFE, 0x98, 0xBA, // data - 'h', - 'e', - 'l', - 'l', - 'o', - ' ', - 'w', - 'o', - 'r', - 'l', - 'd', - '!', + 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; // clang-format on @@ -3182,9 +3132,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { @@ -3193,19 +3143,9 @@ // public flags (version, 8 byte connection_id) 0x0D, // connection_id - 0x10, - 0x32, - 0x54, - 0x76, - 0x98, - 0xBA, - 0xDC, - 0xFE, + 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, // version tag - 'Q', - '0', - GetQuicVersionDigitTens(), - GetQuicVersionDigitOnes(), + 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(), }; // clang-format on @@ -3272,9 +3212,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } // TODO(jri): Add test for tuncated packets in which the original ack frame had @@ -3386,9 +3326,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) { @@ -3451,9 +3391,9 @@ ASSERT_TRUE(data != nullptr); // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks. EXPECT_EQ(36u, data->length()); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildStopWaitingPacket) { @@ -3498,9 +3438,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildRstFramePacketQuic) { @@ -3601,9 +3541,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildGoAwayPacket) { @@ -3656,9 +3596,9 @@ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildWindowUpdatePacket) { @@ -3876,9 +3816,9 @@ framer_.BuildPublicResetPacket(reset_packet)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) { @@ -3930,9 +3870,9 @@ framer_.BuildPublicResetPacket(reset_packet)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, BuildFecPacket) { @@ -3974,9 +3914,9 @@ scoped_ptr<QuicPacket> data(framer_.BuildFecPacket(header, redundancy)); ASSERT_TRUE(data != nullptr); - test::CompareCharArraysWithHexError("constructed packet", - data->data(), data->length(), - AsChars(packet), arraysize(packet)); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + arraysize(packet)); } TEST_P(QuicFramerTest, EncryptPacket) {
diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc index c47f14f..0d93cf9a 100644 --- a/net/quic/quic_headers_stream.cc +++ b/net/quic/quic_headers_stream.cc
@@ -204,12 +204,11 @@ QuicHeadersStream::~QuicHeadersStream() {} -size_t QuicHeadersStream::WriteHeaders( - QuicStreamId stream_id, - const SpdyHeaderBlock& headers, - bool fin, - QuicPriority priority, - QuicAckListenerInterface* ack_notifier_delegate) { +size_t QuicHeadersStream::WriteHeaders(QuicStreamId stream_id, + const SpdyHeaderBlock& headers, + bool fin, + SpdyPriority priority, + QuicAckListenerInterface* ack_listener) { SpdyHeadersIR headers_frame(stream_id); headers_frame.set_header_block(headers); headers_frame.set_fin(fin); @@ -220,7 +219,30 @@ scoped_ptr<SpdySerializedFrame> frame( spdy_framer_.SerializeFrame(headers_frame)); WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, - ack_notifier_delegate); + ack_listener); + return frame->size(); +} + +size_t QuicHeadersStream::WritePushPromise( + QuicStreamId original_stream_id, + QuicStreamId promised_stream_id, + const SpdyHeaderBlock& headers, + QuicAckListenerInterface* ack_listener) { + if (session()->perspective() == Perspective::IS_CLIENT) { + LOG(DFATAL) << "Client shouldn't send PUSH_PROMISE"; + return 0; + } + + SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id); + push_promise.set_header_block(headers); + // PUSH_PROMISE must not be the last frame sent out, at least followed by + // response headers. + push_promise.set_fin(false); + + scoped_ptr<SpdySerializedFrame> frame( + spdy_framer_.SerializeFrame(push_promise)); + WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, + ack_listener); return frame->size(); } @@ -253,7 +275,9 @@ } } -QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; } +SpdyPriority QuicHeadersStream::Priority() const { + return net::kHighestPriority; // The smallest priority is also the highest +} void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id, SpdyPriority priority,
diff --git a/net/quic/quic_headers_stream.h b/net/quic/quic_headers_stream.h index 645b66b..ef1bfef 100644 --- a/net/quic/quic_headers_stream.h +++ b/net/quic/quic_headers_stream.h
@@ -32,12 +32,20 @@ size_t WriteHeaders(QuicStreamId stream_id, const SpdyHeaderBlock& headers, bool fin, - QuicPriority priority, - QuicAckListenerInterface* ack_notifier_delegate); + SpdyPriority priority, + QuicAckListenerInterface* ack_listener); + + // Write |headers| for |promised_stream_id| on |original_stream_id| in a + // PUSH_PROMISE frame to peer. Return the size, in bytes, of the resulting + // SPDY frame. + size_t WritePushPromise(QuicStreamId original_stream_id, + QuicStreamId promised_stream_id, + const SpdyHeaderBlock& headers, + QuicAckListenerInterface* ack_listener); // ReliableQuicStream implementation void OnDataAvailable() override; - QuicPriority EffectivePriority() const override; + SpdyPriority Priority() const override; private: class SpdyFramerVisitor;
diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index 33eae0c..c676492 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc
@@ -13,6 +13,7 @@ #include "net/spdy/spdy_alt_svc_wire_format.h" #include "net/spdy/spdy_protocol.h" #include "net/spdy/spdy_test_utils.h" +#include "net/test/gtest_util.h" #include "testing/gtest/include/gtest/gtest.h" using base::StringPiece; @@ -124,7 +125,8 @@ headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)), body_("hello world"), framer_(HTTP2), - stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, "") { + stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""), + next_promised_stream_id_(2) { headers_[":version"] = "HTTP/1.1"; headers_[":status"] = "200 Ok"; headers_["content-length"] = "11"; @@ -155,7 +157,7 @@ void WriteHeadersAndExpectSynStream(QuicStreamId stream_id, bool fin, - QuicPriority priority) { + SpdyPriority priority) { WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM); } @@ -166,7 +168,7 @@ void WriteHeadersAndCheckData(QuicStreamId stream_id, bool fin, - QuicPriority priority, + SpdyPriority priority, SpdyFrameType type) { // Write the headers and capture the outgoing data EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr)) @@ -222,6 +224,8 @@ QuicConnectionPeer::CloseConnection(connection_); } + QuicStreamId NextPromisedStreamId() { return next_promised_stream_id_++; } + static const bool kFrameComplete = true; static const bool kHasPriority = true; @@ -236,6 +240,7 @@ SpdyFramer framer_; StrictMock<MockVisitor> visitor_; QuicStreamFrame stream_frame_; + QuicStreamId next_promised_stream_id_; }; INSTANTIATE_TEST_CASE_P(Tests, @@ -246,8 +251,8 @@ EXPECT_EQ(3u, headers_stream_->id()); } -TEST_P(QuicHeadersStreamTest, EffectivePriority) { - EXPECT_EQ(0u, headers_stream_->EffectivePriority()); +TEST_P(QuicHeadersStreamTest, Priority) { + EXPECT_EQ(0u, headers_stream_->Priority()); } TEST_P(QuicHeadersStreamTest, WriteHeaders) { @@ -257,7 +262,7 @@ if (perspective() == Perspective::IS_SERVER) { WriteHeadersAndExpectSynReply(stream_id, fin); } else { - for (QuicPriority priority = 0; priority < 7; ++priority) { + for (SpdyPriority priority = 0; priority < 7; ++priority) { // TODO(rch): implement priorities correctly. WriteHeadersAndExpectSynStream(stream_id, fin, 0); } @@ -266,11 +271,42 @@ } } +TEST_P(QuicHeadersStreamTest, WritePushPromises) { + for (QuicStreamId stream_id = kClientDataStreamId1; + stream_id < kClientDataStreamId3; stream_id += 2) { + QuicStreamId promised_stream_id = NextPromisedStreamId(); + if (perspective() == Perspective::IS_SERVER) { + // Write the headers and capture the outgoing data + EXPECT_CALL(session_, + WritevData(kHeadersStreamId, _, _, false, _, nullptr)) + .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); + headers_stream_->WritePushPromise(stream_id, promised_stream_id, headers_, + nullptr); + + // Parse the outgoing data and check that it matches was was written. + EXPECT_CALL(visitor_, + OnPushPromise(stream_id, promised_stream_id, kFrameComplete)); + EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _)) + .WillRepeatedly(WithArgs<1, 2>( + Invoke(this, &QuicHeadersStreamTest::SaveHeaderData))); + framer_.ProcessInput(saved_data_.data(), saved_data_.length()); + EXPECT_FALSE(framer_.HasError()) + << SpdyFramer::ErrorCodeToString(framer_.error_code()); + CheckHeaders(); + saved_data_.clear(); + } else { + EXPECT_DFATAL(headers_stream_->WritePushPromise( + stream_id, promised_stream_id, headers_, nullptr), + "Client shouldn't send PUSH_PROMISE"); + } + } +} + TEST_P(QuicHeadersStreamTest, ProcessRawData) { for (QuicStreamId stream_id = kClientDataStreamId1; stream_id < kClientDataStreamId3; stream_id += 2) { - for (bool fin : kFins) { - for (QuicPriority priority = 0; priority < 7; ++priority) { + for (bool fin : {false, true}) { + for (SpdyPriority priority = 0; priority < 7; ++priority) { // Replace with "WriteHeadersAndSaveData" scoped_ptr<SpdySerializedFrame> frame; if (perspective() == Perspective::IS_SERVER) { @@ -387,8 +423,8 @@ headers_["key2"] = string(1 << 13, '.'); for (QuicStreamId stream_id = kClientDataStreamId1; stream_id < kClientDataStreamId3; stream_id += 2) { - for (bool fin : kFins) { - for (QuicPriority priority = 0; priority < 7; ++priority) { + for (bool fin : {false, true}) { + for (SpdyPriority priority = 0; priority < 7; ++priority) { // Replace with "WriteHeadersAndSaveData" scoped_ptr<SpdySerializedFrame> frame; if (perspective() == Perspective::IS_SERVER) {
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 2414d0f..5d274d8c 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -120,7 +120,7 @@ return ERR_CONNECTION_CLOSED; } - QuicPriority priority = ConvertRequestPriorityToQuicPriority(priority_); + SpdyPriority priority = ConvertRequestPriorityToQuicPriority(priority_); stream_->set_priority(priority); // Store the serialized request headers. CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, HTTP2,
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc index 108e9e0..838f105d 100644 --- a/net/quic/quic_http_stream_test.cc +++ b/net/quic/quic_http_stream_test.cc
@@ -264,7 +264,7 @@ bool fin, RequestPriority request_priority, size_t* spdy_headers_frame_length) { - QuicPriority priority = + SpdyPriority priority = ConvertRequestPriorityToQuicPriority(request_priority); return maker_.MakeRequestHeadersPacket( packet_number, stream_id_, kIncludeVersion, fin, priority, @@ -822,15 +822,14 @@ QuicReliableClientStream* reliable_stream = QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get()); DCHECK(reliable_stream); - DCHECK_EQ(QuicWriteBlockedList::kHighestPriority, - reliable_stream->EffectivePriority()); + DCHECK_EQ(kHighestPriority, reliable_stream->Priority()); EXPECT_EQ(OK, stream_->SendRequest(headers_, &response_, callback_.callback())); // Check that priority has now dropped back to MEDIUM. - DCHECK_EQ(MEDIUM, ConvertQuicPriorityToRequestPriority( - reliable_stream->EffectivePriority())); + DCHECK_EQ(MEDIUM, + ConvertQuicPriorityToRequestPriority(reliable_stream->Priority())); // Ack the request. ProcessPacket(ConstructAckPacket(1, 0, 0)); @@ -875,14 +874,12 @@ DCHECK(reliable_stream); QuicReliableClientStream::Delegate* delegate = reliable_stream->GetDelegate(); DCHECK(delegate); - DCHECK_EQ(QuicWriteBlockedList::kHighestPriority, - reliable_stream->EffectivePriority()); + DCHECK_EQ(kHighestPriority, reliable_stream->Priority()); - // Set Delegate to nullptr and make sure EffectivePriority returns highest + // Set Delegate to nullptr and make sure Priority returns highest // priority. reliable_stream->SetDelegate(nullptr); - DCHECK_EQ(QuicWriteBlockedList::kHighestPriority, - reliable_stream->EffectivePriority()); + DCHECK_EQ(kHighestPriority, reliable_stream->Priority()); reliable_stream->SetDelegate(delegate); EXPECT_EQ(0, stream_->GetTotalSentBytes());
diff --git a/net/quic/quic_http_utils.cc b/net/quic/quic_http_utils.cc index 60fbd9a..856427b 100644 --- a/net/quic/quic_http_utils.cc +++ b/net/quic/quic_http_utils.cc
@@ -6,15 +6,15 @@ namespace net { -QuicPriority ConvertRequestPriorityToQuicPriority( +SpdyPriority ConvertRequestPriorityToQuicPriority( const RequestPriority priority) { DCHECK_GE(priority, MINIMUM_PRIORITY); DCHECK_LE(priority, MAXIMUM_PRIORITY); - return static_cast<QuicPriority>(HIGHEST - priority); + return static_cast<SpdyPriority>(HIGHEST - priority); } -NET_EXPORT_PRIVATE RequestPriority ConvertQuicPriorityToRequestPriority( - QuicPriority priority) { +NET_EXPORT_PRIVATE RequestPriority +ConvertQuicPriorityToRequestPriority(SpdyPriority priority) { // Handle invalid values gracefully. return (priority >= 5) ? IDLE : static_cast<RequestPriority>(HIGHEST - priority); @@ -23,7 +23,7 @@ scoped_ptr<base::Value> QuicRequestNetLogCallback( QuicStreamId stream_id, const SpdyHeaderBlock* headers, - QuicPriority priority, + SpdyPriority priority, NetLogCaptureMode capture_mode) { scoped_ptr<base::DictionaryValue> dict(static_cast<base::DictionaryValue*>( SpdyHeaderBlockNetLogCallback(headers, capture_mode).release()));
diff --git a/net/quic/quic_http_utils.h b/net/quic/quic_http_utils.h index 82306d6..1bde98a 100644 --- a/net/quic/quic_http_utils.h +++ b/net/quic/quic_http_utils.h
@@ -10,20 +10,21 @@ #include "net/base/request_priority.h" #include "net/quic/quic_protocol.h" #include "net/spdy/spdy_header_block.h" +#include "net/spdy/spdy_protocol.h" namespace net { -NET_EXPORT_PRIVATE QuicPriority ConvertRequestPriorityToQuicPriority( - RequestPriority priority); +NET_EXPORT_PRIVATE SpdyPriority +ConvertRequestPriorityToQuicPriority(RequestPriority priority); -NET_EXPORT_PRIVATE RequestPriority ConvertQuicPriorityToRequestPriority( - QuicPriority priority); +NET_EXPORT_PRIVATE RequestPriority +ConvertQuicPriorityToRequestPriority(SpdyPriority priority); // Converts a SpdyHeaderBlock and priority into NetLog event parameters. NET_EXPORT scoped_ptr<base::Value> QuicRequestNetLogCallback( QuicStreamId stream_id, const SpdyHeaderBlock* headers, - QuicPriority priority, + SpdyPriority priority, NetLogCaptureMode capture_mode); } // namespace net
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 8c531ecc..436928081 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -262,7 +262,7 @@ bool should_include_version, bool fin, const SpdyHeaderBlock& headers) { - QuicPriority priority = + SpdyPriority priority = ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY); return maker_.MakeRequestHeadersPacket(packet_number, stream_id, should_include_version, fin,
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index c2a400b..d76488e 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc
@@ -69,8 +69,10 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id, QuicFramer* framer, - QuicRandom* random_generator) - : connection_id_(connection_id), + QuicRandom* random_generator, + DelegateInterface* delegate) + : delegate_(delegate), + connection_id_(connection_id), encryption_level_(ENCRYPTION_NONE), framer_(framer), random_bool_source_(new QuicRandomBoolSource(random_generator)), @@ -237,6 +239,28 @@ QuicFramer::GetMinSequenceNumberLength(delta * 4); } +bool QuicPacketCreator::ConsumeData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + bool fin, + bool needs_padding, + QuicFrame* frame) { + if (!HasRoomForStreamFrame(id, offset)) { + Flush(); + return false; + } + + UniqueStreamBuffer buffer; + CreateStreamFrame(id, iov, iov_offset, offset, fin, frame, &buffer); + + bool success = AddFrame(*frame, + /*save_retransmittable_frames=*/true, needs_padding, + std::move(buffer)); + DCHECK(success); + return true; +} + bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id, QuicStreamOffset offset) const { // TODO(jri): This is a simple safe decision for now, but make @@ -413,6 +437,19 @@ return packet; } +void QuicPacketCreator::Flush() { + if (!HasPendingFrames()) { + return; + } + + // TODO(rtenneti): Change the default 64 alignas value (used the default + // value from CACHELINE_SIZE). + ALIGNAS(64) char seralized_packet_buffer[kMaxPacketSize]; + SerializedPacket serialized_packet = + SerializePacket(seralized_packet_buffer, kMaxPacketSize); + delegate_->OnSerializedPacket(&serialized_packet); +} + bool QuicPacketCreator::HasPendingFrames() const { return !queued_frames_.empty(); } @@ -649,6 +686,8 @@ frame, BytesFree(), queued_frames_.empty(), true, is_in_fec_group, packet_number_length_); if (frame_len == 0) { + // Current open packet is full. + Flush(); return false; } DCHECK_LT(0u, packet_size_);
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h index 31646ec7..5256fb9 100644 --- a/net/quic/quic_packet_creator.h +++ b/net/quic/quic_packet_creator.h
@@ -29,10 +29,20 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { public: + // A delegate interface for further processing serialized packet. + class NET_EXPORT_PRIVATE DelegateInterface { + public: + virtual ~DelegateInterface() {} + // Called when a packet is serialized. Delegate does not take the ownership + // of |serialized_packet|. + virtual void OnSerializedPacket(SerializedPacket* serialized_packet) = 0; + }; + // QuicRandom* required for packet entropy. QuicPacketCreator(QuicConnectionId connection_id, QuicFramer* framer, - QuicRandom* random_generator); + QuicRandom* random_generator, + DelegateInterface* delegate); ~QuicPacketCreator(); @@ -74,21 +84,22 @@ QuicStreamOffset offset, InFecGroup is_in_fec_group); - bool HasRoomForStreamFrame(QuicStreamId id, QuicStreamOffset offset) const; + // Returns false and flushes all pending frames if current open packet is + // full. + // If current packet is not full, converts a raw payload into a stream frame + // that fits into the open packet and adds it to the packet. + // The payload begins at |iov_offset| into the |iov|. + bool ConsumeData(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + bool fin, + bool needs_padding, + QuicFrame* frame); - // Converts a raw payload to a frame which fits into the currently open - // packet. The payload begins at |iov_offset| into the |iov|. - // Returns the number of bytes consumed from data. - // If data is empty and fin is true, the expected behavior is to consume the - // fin but return 0. If any data is consumed, it will be copied into a - // new buffer that |frame| will point to and will be stored in |buffer|. - size_t CreateStreamFrame(QuicStreamId id, - QuicIOVector iov, - size_t iov_offset, - QuicStreamOffset offset, - bool fin, - QuicFrame* frame, - UniqueStreamBuffer* buffer); + // Returns true if current open packet can accommodate more stream frames of + // stream |id| at |offset|, false otherwise. + bool HasRoomForStreamFrame(QuicStreamId id, QuicStreamOffset offset) const; // Serializes all frames into a single packet. All frames must fit into a // single packet. Also, sets the entropy hash of the serialized packet to a @@ -107,6 +118,10 @@ char* buffer, size_t buffer_len); + // Serializes all added frames into a single packet and invokes the delegate_ + // to further process the SerializedPacket. + void Flush(); + // Returns true if there are frames pending to be serialized. bool HasPendingFrames() const; @@ -146,8 +161,9 @@ // TODO(jri): AddSavedFrame calls AddFrame, which only saves the frame // if it is a stream frame, not other types of frames. Fix this API; // add a AddNonSavedFrame method. - // Adds |frame| to the packet creator's list of frames to be serialized. - // Returns false if the frame doesn't fit into the current packet. + // Tries to add |frame| to the packet creator's std::list of frames to be + // serialized. If the frame does not fit into the current packet, flushes the + // packet and returns false. bool AddSavedFrame(const QuicFrame& frame); // Identical to AddSavedFrame, but takes ownership of the buffer. @@ -157,16 +173,6 @@ // to cause the packet to be padded. bool AddPaddedSavedFrame(const QuicFrame& frame, UniqueStreamBuffer buffer); - // Serializes all frames which have been added and adds any which should be - // retransmitted to |retransmittable_frames| if it's not nullptr. All frames - // must fit into a single packet. Sets the entropy hash of the serialized - // packet to a random bool and returns that value as a member of - // SerializedPacket. Also, sets |serialized_frames| in the SerializedPacket to - // the corresponding RetransmittableFrames if any frames are to be - // retransmitted. - // Fails if |buffer_len| isn't long enough for the encrypted packet. - SerializedPacket SerializePacket(char* encrypted_buffer, size_t buffer_len); - // Packetize FEC data. All frames must fit into a single packet. Also, sets // the entropy hash of the serialized packet to a random bool and returns // that value as a member of SerializedPacket. @@ -226,7 +232,7 @@ // To turn off FEC protection, use StopFecProtectingPackets(). void set_max_packets_per_fec_group(size_t max_packets_per_fec_group); - // Returns the currently open FEC group's number. Returns 0 when FEC is + // Returns the current open FEC group's number. Returns 0 when FEC is // disabled or no FEC group is open. QuicFecGroupNumber fec_group_number(); @@ -235,6 +241,20 @@ static bool ShouldRetransmit(const QuicFrame& frame); + // Converts a raw payload to a frame which fits into the current open + // packet. The payload begins at |iov_offset| into the |iov|. + // Returns the number of bytes consumed from data. + // If data is empty and fin is true, the expected behavior is to consume the + // fin but return 0. If any data is consumed, it will be copied into a + // new buffer that |frame| will point to and will be stored in |buffer|. + size_t CreateStreamFrame(QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + bool fin, + QuicFrame* frame, + UniqueStreamBuffer* buffer); + // Copies |length| bytes from iov starting at offset |iov_offset| into buffer. // |iov| must be at least iov_offset+length total length and buffer must be // at least |length| long. @@ -258,6 +278,8 @@ // Allows a frame to be added without creating retransmittable frames. // Particularly useful for retransmits using SerializeAllFrames(). + // If current open packet cannot accommodate |frame|, returns false and + // flushes all pending frames. bool AddFrame(const QuicFrame& frame, bool save_retransmittable_frames, bool needs_padding, @@ -268,6 +290,18 @@ // padding frame. void MaybeAddPadding(); + // Serializes all frames which have been added and adds any which should be + // retransmitted to queued_retransmittable_frames_ if it's not nullptr. All + // frames must fit into a single packet. Sets the entropy hash of the + // serialized packet to a random bool and returns that value as a member of + // SerializedPacket. Also, sets |serialized_frames| in the SerializedPacket to + // the corresponding RetransmittableFrames if any frames are to be + // retransmitted. + // Fails if |buffer_len| isn't long enough for the encrypted packet. + SerializedPacket SerializePacket(char* encrypted_buffer, size_t buffer_len); + + // Does not own this delegate. + DelegateInterface* delegate_; QuicConnectionId connection_id_; EncryptionLevel encryption_level_; QuicFramer* framer_;
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc index 8544e89..a39d832 100644 --- a/net/quic/quic_packet_creator_test.cc +++ b/net/quic/quic_packet_creator_test.cc
@@ -27,6 +27,7 @@ using testing::InSequence; using testing::Return; using testing::SaveArg; +using testing::StrictMock; using testing::_; namespace net { @@ -77,7 +78,38 @@ return params; } +class MockDelegate : public QuicPacketCreator::DelegateInterface { + public: + MockDelegate() {} + ~MockDelegate() override {} + + MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockDelegate); +}; + class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { + public: + void ClearSerializedPacket(SerializedPacket* serialized_packet) { + if (serialized_packet == nullptr) { + return; + } + + delete serialized_packet->retransmittable_frames; + delete serialized_packet->packet; + } + + void SaveSerializedPacket(SerializedPacket* serialized_packet) { + if (serialized_packet == nullptr) { + return; + } + + serialized_packet_ = *serialized_packet; + serialized_packet_.packet = serialized_packet->packet->Clone(); + delete serialized_packet->packet; + } + protected: QuicPacketCreatorTest() : server_framer_(SupportedVersions(GetParam().version), @@ -88,7 +120,8 @@ Perspective::IS_CLIENT), connection_id_(2), data_("foo"), - creator_(connection_id_, &client_framer_, &mock_random_) { + creator_(connection_id_, &client_framer_, &mock_random_, &delegate_), + serialized_packet_(creator_.NoPacket()) { creator_.set_connection_id_length(GetParam().connection_id_length); client_framer_.set_visitor(&framer_visitor_); client_framer_.set_received_entropy_calculator(&entropy_calculator_); @@ -154,13 +187,15 @@ QuicFrames frames_; QuicFramer server_framer_; QuicFramer client_framer_; - testing::StrictMock<MockFramerVisitor> framer_visitor_; + StrictMock<MockFramerVisitor> framer_visitor_; + StrictMock<MockDelegate> delegate_; QuicConnectionId connection_id_; string data_; struct iovec iov_; MockRandom mock_random_; QuicPacketCreator creator_; MockEntropyCalculator entropy_calculator_; + SerializedPacket serialized_packet_; }; // Run all packet creator tests with all supported versions of QUIC, and with @@ -254,11 +289,14 @@ creator_.AddSavedFrame(frames_[0]); QuicPacketCreatorPeer::SetNextPacketNumberLength(&creator_, PACKET_4BYTE_PACKET_NUMBER); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); + + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); // The packet number length will not change mid-packet. - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, serialized.packet_number_length); + EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, + serialized_packet_.packet_number_length); { InSequence s; @@ -270,13 +308,14 @@ EXPECT_CALL(framer_visitor_, OnAckFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } - ProcessPacket(serialized.packet); - delete serialized.packet; + ProcessPacket(serialized_packet_.packet); + ClearSerializedPacket(&serialized_packet_); creator_.AddSavedFrame(frames_[0]); - serialized = creator_.SerializePacket(buffer, kMaxPacketSize); + creator_.Flush(); // Now the actual packet number length should have changed. - EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, serialized.packet_number_length); + EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, + serialized_packet_.packet_number_length); delete frames_[0].ack_frame; { @@ -289,8 +328,8 @@ EXPECT_CALL(framer_visitor_, OnAckFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } - ProcessPacket(serialized.packet); - delete serialized.packet; + ProcessPacket(serialized_packet_.packet); + ClearSerializedPacket(&serialized_packet_); } TEST_P(QuicPacketCreatorTest, ChangeSequenceNumberLengthMidPacket) { @@ -315,11 +354,13 @@ EXPECT_TRUE(creator_.HasPendingFrames()); // Ensure the packet is successfully created. - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized.packet); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, serialized.packet_number_length); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); + EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, + serialized_packet_.packet_number_length); // Verify that header in transmitted packet has 1 byte sequence length. QuicPacketHeader header; @@ -335,10 +376,10 @@ EXPECT_CALL(framer_visitor_, OnStopWaitingFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } - ProcessPacket(serialized.packet); + ProcessPacket(serialized_packet_.packet); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, header.public_header.packet_number_length); - delete serialized.packet; + ClearSerializedPacket(&serialized_packet_); // Packet 2. EXPECT_FALSE(creator_.HasPendingFrames()); @@ -348,9 +389,10 @@ EXPECT_TRUE(creator_.HasPendingFrames()); // Ensure the packet is successfully created. - serialized = creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized.packet); - EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, serialized.packet_number_length); + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); + EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, + serialized_packet_.packet_number_length); // Verify that header in transmitted packet has 4 byte sequence length. { @@ -364,11 +406,11 @@ EXPECT_CALL(framer_visitor_, OnStopWaitingFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } - ProcessPacket(serialized.packet); + ProcessPacket(serialized_packet_.packet); EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, header.public_header.packet_number_length); - delete serialized.packet; + ClearSerializedPacket(&serialized_packet_); delete ack_frame.ack_frame; } @@ -390,10 +432,12 @@ // Change the packet number length mid-FEC group and it should not change. QuicPacketCreatorPeer::SetNextPacketNumberLength(&creator_, PACKET_4BYTE_PACKET_NUMBER); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, serialized.packet_number_length); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, + serialized_packet_.packet_number_length); { InSequence s; @@ -406,13 +450,14 @@ EXPECT_CALL(framer_visitor_, OnAckFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } - ProcessPacket(serialized.packet); - delete serialized.packet; + ProcessPacket(serialized_packet_.packet); + ClearSerializedPacket(&serialized_packet_); // Generate Packet 2. creator_.AddSavedFrame(frames_[0]); - serialized = creator_.SerializePacket(buffer, kMaxPacketSize); - EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, serialized.packet_number_length); + creator_.Flush(); + EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, + serialized_packet_.packet_number_length); { InSequence s; @@ -425,8 +470,8 @@ EXPECT_CALL(framer_visitor_, OnAckFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } - ProcessPacket(serialized.packet); - delete serialized.packet; + ProcessPacket(serialized_packet_.packet); + ClearSerializedPacket(&serialized_packet_); // Should return false since we do not have enough packets in the FEC group to // trigger an FEC packet. @@ -435,7 +480,8 @@ ASSERT_TRUE(creator_.ShouldSendFec(/*force_close=*/true)); // Force generation of FEC packet. - serialized = creator_.SerializeFec(buffer, kMaxPacketSize); + char buffer[kMaxPacketSize]; + SerializedPacket serialized = creator_.SerializeFec(buffer, kMaxPacketSize); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, serialized.packet_number_length); ASSERT_EQ(3u, serialized.packet_number); @@ -450,13 +496,13 @@ EXPECT_CALL(framer_visitor_, OnPacketComplete()); } ProcessPacket(serialized.packet); - delete serialized.packet; + ClearSerializedPacket(&serialized); // Ensure the next FEC group starts using the new packet number length. serialized = creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, serialized.packet_number_length); delete frames_[0].ack_frame; - delete serialized.packet; + ClearSerializedPacket(&serialized); } TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) { @@ -498,8 +544,9 @@ QuicFrame frame; QuicIOVector io_vector(MakeIOVector("fake handshake message data")); UniqueStreamBuffer stream_buffer; - creator_.CreateStreamFrame(kCryptoStreamId, io_vector, 0u, 0u, false, &frame, - &stream_buffer); + QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId, + io_vector, 0u, 0u, false, &frame, + &stream_buffer); RetransmittableFrames frames(ENCRYPTION_NONE); frames.AddFrame(frame); frames.set_needs_padding(true); @@ -522,8 +569,9 @@ QuicFrame frame; QuicIOVector io_vector(MakeIOVector(data)); UniqueStreamBuffer stream_buffer; - creator_.CreateStreamFrame(kCryptoStreamId, io_vector, 0, kOffset, false, - &frame, &stream_buffer); + QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId, + io_vector, 0, kOffset, false, + &frame, &stream_buffer); RetransmittableFrames frames(ENCRYPTION_NONE); frames.AddFrame(frame); frames.set_needs_padding(true); @@ -629,12 +677,11 @@ // Add a stream frame to the creator. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(1u, io_vector, 0u, 0u, false, - &frame, &stream_buffer); - EXPECT_EQ(4u, consumed); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); - EXPECT_TRUE(creator_.AddSavedFrame(frame)); + size_t consumed = frame.stream_frame->data.length(); + EXPECT_EQ(4u, consumed); EXPECT_TRUE(creator_.HasPendingFrames()); // Enable FEC protection, and send FEC packet every 6 packets. @@ -645,11 +692,9 @@ EXPECT_FALSE(creator_.IsFecProtected()); // Serialize packet for transmission. - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); - delete serialized.packet; - delete serialized.retransmittable_frames; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); + creator_.Flush(); EXPECT_FALSE(creator_.HasPendingFrames()); // Since all pending frames have been serialized, turning FEC on should work. @@ -657,39 +702,39 @@ EXPECT_TRUE(creator_.IsFecProtected()); } -TEST_P(QuicPacketCreatorTest, CreateStreamFrame) { +TEST_P(QuicPacketCreatorTest, ConsumeData) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(1u, io_vector, 0u, 0u, false, - &frame, &stream_buffer); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t consumed = frame.stream_frame->data.length(); EXPECT_EQ(4u, consumed); CheckStreamFrame(frame, 1u, "test", 0u, false); - RetransmittableFrames cleanup_frames(ENCRYPTION_NONE); - cleanup_frames.AddFrame(frame); + EXPECT_TRUE(creator_.HasPendingFrames()); } -TEST_P(QuicPacketCreatorTest, CreateStreamFrameFin) { +TEST_P(QuicPacketCreatorTest, ConsumeDataFin) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(1u, io_vector, 0u, 10u, true, - &frame, &stream_buffer); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 10u, true, false, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t consumed = frame.stream_frame->data.length(); EXPECT_EQ(4u, consumed); CheckStreamFrame(frame, 1u, "test", 10u, true); - RetransmittableFrames cleanup_frames(ENCRYPTION_NONE); - cleanup_frames.AddFrame(frame); + EXPECT_TRUE(creator_.HasPendingFrames()); } -TEST_P(QuicPacketCreatorTest, CreateStreamFrameFinOnly) { +TEST_P(QuicPacketCreatorTest, ConsumeDataFinOnly) { QuicFrame frame; QuicIOVector io_vector(nullptr, 0, 0); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(1u, io_vector, 0u, 0u, true, - &frame, &stream_buffer); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t consumed = frame.stream_frame->data.length(); EXPECT_EQ(0u, consumed); CheckStreamFrame(frame, 1u, string(), 0u, true); - delete frame.stream_frame; + EXPECT_TRUE(creator_.HasPendingFrames()); } TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) { @@ -704,26 +749,24 @@ if (should_have_room) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("testdata")); - UniqueStreamBuffer stream_buffer; - size_t bytes_consumed = - creator_.CreateStreamFrame(kClientDataStreamId1, io_vector, 0u, - kOffset, false, &frame, &stream_buffer); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); + ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, + kOffset, false, false, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t bytes_consumed = frame.stream_frame->data.length(); EXPECT_LT(0u, bytes_consumed); - ASSERT_TRUE(creator_.AddSavedFrame(frame)); - char buffer[kMaxPacketSize]; - SerializedPacket serialized_packet = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized_packet.packet); - delete serialized_packet.packet; - delete serialized_packet.retransmittable_frames; + creator_.Flush(); } } } TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) { // Compute the total overhead for a single frame in packet. - const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) - + GetEncryptionOverhead() + GetStreamFrameOverhead(NOT_IN_FEC_GROUP); + const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + + GetEncryptionOverhead() + + GetStreamFrameOverhead(NOT_IN_FEC_GROUP); size_t capacity = kDefaultMaxPacketSize - overhead; // Now, test various sizes around this size. for (int delta = -5; delta <= 5; ++delta) { @@ -732,9 +775,9 @@ QuicFrame frame; QuicIOVector io_vector(MakeIOVector(data)); UniqueStreamBuffer stream_buffer; - size_t bytes_consumed = - creator_.CreateStreamFrame(kClientDataStreamId1, io_vector, 0u, kOffset, - false, &frame, &stream_buffer); + size_t bytes_consumed = QuicPacketCreatorPeer::CreateStreamFrame( + &creator_, kClientDataStreamId1, io_vector, 0u, kOffset, false, &frame, + &stream_buffer); EXPECT_EQ(capacity - bytes_free, bytes_consumed); ASSERT_TRUE(creator_.AddSavedFrame(frame)); @@ -743,12 +786,11 @@ EXPECT_EQ(2u, creator_.ExpansionOnNewFrame()); size_t expected_bytes_free = bytes_free < 3 ? 0 : bytes_free - 2; EXPECT_EQ(expected_bytes_free, creator_.BytesFree()) << "delta: " << delta; - char buffer[kMaxPacketSize]; - SerializedPacket serialized_packet = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized_packet.packet); - delete serialized_packet.packet; - delete serialized_packet.retransmittable_frames; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); + ClearSerializedPacket(&serialized_packet_); } } @@ -756,8 +798,9 @@ // Enable FEC protection, and send FEC packet every 6 packets. EXPECT_TRUE(SwitchFecProtectionOn(6)); // Compute the total overhead for a single frame in packet. - const size_t overhead = GetPacketHeaderOverhead(IN_FEC_GROUP) - + GetEncryptionOverhead() + GetStreamFrameOverhead(IN_FEC_GROUP); + const size_t overhead = GetPacketHeaderOverhead(IN_FEC_GROUP) + + GetEncryptionOverhead() + + GetStreamFrameOverhead(IN_FEC_GROUP); size_t capacity = kDefaultMaxPacketSize - overhead; // Now, test various sizes around this size. for (int delta = -5; delta <= 5; ++delta) { @@ -766,9 +809,9 @@ QuicFrame frame; QuicIOVector io_vector(MakeIOVector(data)); UniqueStreamBuffer stream_buffer; - size_t bytes_consumed = - creator_.CreateStreamFrame(kClientDataStreamId1, io_vector, 0u, kOffset, - false, &frame, &stream_buffer); + size_t bytes_consumed = QuicPacketCreatorPeer::CreateStreamFrame( + &creator_, kClientDataStreamId1, io_vector, 0u, kOffset, false, &frame, + &stream_buffer); EXPECT_EQ(capacity - bytes_free, bytes_consumed); ASSERT_TRUE(creator_.AddSavedFrame(frame)); @@ -778,12 +821,11 @@ EXPECT_EQ(0u, creator_.ExpansionOnNewFrame()); size_t expected_bytes_free = bytes_free > 0 ? bytes_free : 0; EXPECT_EQ(expected_bytes_free, creator_.BytesFree()) << "delta: " << delta; - char buffer[kMaxPacketSize]; - SerializedPacket serialized_packet = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized_packet.packet); - delete serialized_packet.packet; - delete serialized_packet.retransmittable_frames; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); + ClearSerializedPacket(&serialized_packet_); } } @@ -800,26 +842,26 @@ QuicFrame frame; QuicIOVector io_vector(MakeIOVector(data)); - UniqueStreamBuffer stream_buffer; - size_t bytes_consumed = creator_.CreateStreamFrame( - kCryptoStreamId, io_vector, 0u, kOffset, false, &frame, &stream_buffer); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, kOffset, + false, true, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t bytes_consumed = frame.stream_frame->data.length(); EXPECT_LT(0u, bytes_consumed); - ASSERT_TRUE(creator_.AddPaddedSavedFrame(frame, nullptr)); - char buffer[kMaxPacketSize]; - SerializedPacket serialized_packet = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized_packet.packet); + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); // If there is not enough space in the packet to fit a padding frame // (1 byte) and to expand the stream frame (another 2 bytes) the packet // will not be padded. if (bytes_free < 3) { EXPECT_EQ(kDefaultMaxPacketSize - bytes_free, - serialized_packet.packet->length()); + serialized_packet_.packet->length()); } else { - EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet.packet->length()); + EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.packet->length()); } - delete serialized_packet.packet; - delete serialized_packet.retransmittable_frames; + ClearSerializedPacket(&serialized_packet_); } } @@ -836,24 +878,22 @@ QuicFrame frame; QuicIOVector io_vector(MakeIOVector(data)); - UniqueStreamBuffer stream_buffer; - size_t bytes_consumed = - creator_.CreateStreamFrame(kClientDataStreamId1, io_vector, 0u, kOffset, - false, &frame, &stream_buffer); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, + kOffset, false, false, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t bytes_consumed = frame.stream_frame->data.length(); EXPECT_LT(0u, bytes_consumed); - ASSERT_TRUE(creator_.AddSavedFrame(frame)); - char buffer[kMaxPacketSize]; - SerializedPacket serialized_packet = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized_packet.packet); + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); if (bytes_free > 0) { EXPECT_EQ(kDefaultMaxPacketSize - bytes_free, - serialized_packet.packet->length()); + serialized_packet_.packet->length()); } else { - EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet.packet->length()); + EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.packet->length()); } - delete serialized_packet.packet; - delete serialized_packet.retransmittable_frames; + ClearSerializedPacket(&serialized_packet_); } } @@ -958,7 +998,7 @@ delete serialized.packet; } -TEST_P(QuicPacketCreatorTest, CreateStreamFrameTooLarge) { +TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) { if (!GetParam().version_serialization) { creator_.StopSendingVersion(); } @@ -972,17 +1012,19 @@ QuicFrame frame; const string too_long_payload(payload_length * 2, 'a'); QuicIOVector io_vector(MakeIOVector(too_long_payload)); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(1u, io_vector, 0u, 0u, true, - &frame, &stream_buffer); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t consumed = frame.stream_frame->data.length(); EXPECT_EQ(payload_length, consumed); const string payload(payload_length, 'a'); CheckStreamFrame(frame, 1u, payload, 0u, false); - RetransmittableFrames cleanup_frames(ENCRYPTION_NONE); - cleanup_frames.AddFrame(frame); + creator_.Flush(); + ClearSerializedPacket(&serialized_packet_); } -TEST_P(QuicPacketCreatorTest, AddFrameAndSerialize) { +TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) { if (!GetParam().version_serialization) { creator_.StopSendingVersion(); } @@ -1003,12 +1045,11 @@ QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(1u, io_vector, 0u, 0u, false, - &frame, &stream_buffer); - EXPECT_EQ(4u, consumed); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); - EXPECT_TRUE(creator_.AddSavedFrame(frame)); + size_t consumed = frame.stream_frame->data.length(); + EXPECT_EQ(4u, consumed); EXPECT_TRUE(creator_.HasPendingFrames()); QuicPaddingFrame padding_frame; @@ -1016,20 +1057,20 @@ EXPECT_TRUE(creator_.HasPendingFrames()); EXPECT_EQ(0u, creator_.BytesFree()); + // Packet is full. Creator will flush. + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); EXPECT_FALSE(creator_.AddSavedFrame(QuicFrame(&ack_frame))); // Ensure the packet is successfully created. - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized.packet); - delete serialized.packet; - ASSERT_TRUE(serialized.retransmittable_frames); - RetransmittableFrames* retransmittable = serialized.retransmittable_frames; + ASSERT_TRUE(serialized_packet_.packet); + ASSERT_TRUE(serialized_packet_.retransmittable_frames); + RetransmittableFrames* retransmittable = + serialized_packet_.retransmittable_frames; ASSERT_EQ(1u, retransmittable->frames().size()); EXPECT_EQ(STREAM_FRAME, retransmittable->frames()[0].type); ASSERT_TRUE(retransmittable->frames()[0].stream_frame); - delete serialized.retransmittable_frames; + ClearSerializedPacket(&serialized_packet_); EXPECT_FALSE(creator_.HasPendingFrames()); EXPECT_EQ(max_plaintext_size - @@ -1062,29 +1103,26 @@ EXPECT_LT(0u, creator_.BytesFree()); // Make sure that an additional stream frame can be added to the packet. - QuicFrame stream_frame; + QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(2u, io_vector, 0u, 0u, false, - &stream_frame, &stream_buffer); + ASSERT_TRUE( + creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame)); + ASSERT_TRUE(frame.stream_frame); + size_t consumed = frame.stream_frame->data.length(); EXPECT_EQ(4u, consumed); - ASSERT_TRUE(stream_frame.stream_frame); - EXPECT_TRUE(creator_.AddSavedFrame(stream_frame)); EXPECT_TRUE(creator_.HasPendingFrames()); // Ensure the packet is successfully created, and the packet size estimate // matches the serialized packet length. - EXPECT_CALL(entropy_calculator_, - EntropyHash(_)).WillOnce(testing::Return(0)); + EXPECT_CALL(entropy_calculator_, EntropyHash(_)).WillOnce(testing::Return(0)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); size_t est_packet_size = creator_.PacketSize(); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized.packet); - EXPECT_EQ(est_packet_size, - client_framer_.GetMaxPlaintextSize(serialized.packet->length())); - delete serialized.retransmittable_frames; - delete serialized.packet; + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); + EXPECT_EQ(est_packet_size, client_framer_.GetMaxPlaintextSize( + serialized_packet_.packet->length())); + ClearSerializedPacket(&serialized_packet_); } TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithSmallPacketSize) { @@ -1114,16 +1152,15 @@ // Ensure the packet is successfully created, and the packet size estimate // may not match the serialized packet length. - EXPECT_CALL(entropy_calculator_, - EntropyHash(_)).WillOnce(Return(0)); + EXPECT_CALL(entropy_calculator_, EntropyHash(_)).WillOnce(Return(0)); size_t est_packet_size = creator_.PacketSize(); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); - ASSERT_TRUE(serialized.packet); - EXPECT_GE(est_packet_size, - client_framer_.GetMaxPlaintextSize(serialized.packet->length())); - delete serialized.packet; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + ASSERT_TRUE(serialized_packet_.packet); + EXPECT_GE(est_packet_size, client_framer_.GetMaxPlaintextSize( + serialized_packet_.packet->length())); + ClearSerializedPacket(&serialized_packet_); } @@ -1210,22 +1247,18 @@ // Add a stream frame to the creator. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - UniqueStreamBuffer stream_buffer; - size_t consumed = creator_.CreateStreamFrame(1u, io_vector, 0u, 0u, false, - &frame, &stream_buffer); - EXPECT_EQ(4u, consumed); + ASSERT_TRUE( + creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); ASSERT_TRUE(frame.stream_frame); - EXPECT_TRUE(creator_.AddSavedFrame(frame)); + size_t consumed = frame.stream_frame->data.length(); + EXPECT_EQ(4u, consumed); EXPECT_TRUE(creator_.HasPendingFrames()); EXPECT_DFATAL(creator_.ResetFecGroup(), "Cannot reset FEC group with pending frames."); - // Serialize packet for transmission. - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializePacket(buffer, kMaxPacketSize); - delete serialized.packet; - delete serialized.retransmittable_frames; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); + creator_.Flush(); EXPECT_FALSE(creator_.HasPendingFrames()); // Close the FEC Group.
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc index 12ebcfb..37bb3fe 100644 --- a/net/quic/quic_packet_generator.cc +++ b/net/quic/quic_packet_generator.cc
@@ -40,7 +40,7 @@ DelegateInterface* delegate) : delegate_(delegate), debug_delegate_(nullptr), - packet_creator_(connection_id, framer, random_generator), + packet_creator_(connection_id, framer, random_generator, this), batch_mode_(false), fec_timeout_(QuicTime::Delta::Zero()), rtt_multiplier_for_fec_timeout_(kRttMultiplierForFecTimeout), @@ -139,7 +139,7 @@ bool fin_consumed = false; if (!packet_creator_.HasRoomForStreamFrame(id, offset)) { - SerializeAndSendPacket(); + packet_creator_.Flush(); } if (fec_protection == MUST_FEC_PROTECT) { @@ -151,23 +151,22 @@ return QuicConsumedData(0, false); } - int frames_created = 0; while (delegate_->ShouldGeneratePacket( HAS_RETRANSMITTABLE_DATA, has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) { QuicFrame frame; - UniqueStreamBuffer buffer; - size_t bytes_consumed = packet_creator_.CreateStreamFrame( - id, iov, total_bytes_consumed, offset + total_bytes_consumed, fin, - &frame, &buffer); - ++frames_created; - - if (!AddFrame(frame, buffer.Pass(), has_handshake)) { - LOG(DFATAL) << "Failed to add stream frame."; - // Inability to add a STREAM frame creates an unrecoverable hole in a - // the stream, so it's best to close the connection. - delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false); - return QuicConsumedData(0, false); + if (!packet_creator_.ConsumeData(id, iov, total_bytes_consumed, + offset + total_bytes_consumed, fin, + has_handshake, &frame)) { + // Current packet is full and flushed. + continue; } + + // A stream frame is created and added. + size_t bytes_consumed = frame.stream_frame->data.length(); + if (debug_delegate_ != nullptr) { + debug_delegate_->OnFrameAddedToPacket(frame); + } + if (listener != nullptr) { ack_listeners_.push_back(AckListenerWrapper(listener, bytes_consumed)); } @@ -175,13 +174,13 @@ total_bytes_consumed += bytes_consumed; fin_consumed = fin && total_bytes_consumed == iov.total_length; DCHECK(total_bytes_consumed == iov.total_length || - packet_creator_.BytesFree() == 0u); + (bytes_consumed > 0 && packet_creator_.HasPendingFrames())); - if (!InBatchMode() || !packet_creator_.HasRoomForStreamFrame(id, offset)) { + if (!InBatchMode()) { // TODO(rtenneti): remove MaybeSendFecPacketAndCloseGroup() from inside // SerializeAndSendPacket() and make it an explicit call here (and // elsewhere where we call SerializeAndSendPacket?). - SerializeAndSendPacket(); + packet_creator_.Flush(); } if (total_bytes_consumed == iov.total_length) { @@ -228,7 +227,7 @@ if (listener != nullptr) { ack_listeners_.push_back(AckListenerWrapper(listener, 0)); } - SerializeAndSendPacket(); + packet_creator_.Flush(); // The only reason AddFrame can fail is that the packet is too full to fit in // a ping. This is not possible for any sane MTU. DCHECK(success); @@ -253,13 +252,10 @@ // Only add pending frames if we are SURE we can then send the whole packet. while (HasPendingFrames() && (flush || CanSendWithNextPendingFrameAddition())) { - if (!AddNextPendingFrame()) { - // Packet was full, so serialize and send it. - SerializeAndSendPacket(); - } + AddNextPendingFrame(); } - if (packet_creator_.HasPendingFrames() && (flush || !InBatchMode())) { - SerializeAndSendPacket(); + if (flush || !InBatchMode()) { + packet_creator_.Flush(); } MaybeSendFecPacketAndCloseGroup(flush, is_fec_timeout); } @@ -424,40 +420,6 @@ return success; } -void QuicPacketGenerator::SerializeAndSendPacket() { - // The optimized encryption algorithm implementations run faster when - // operating on aligned memory. - // - // TODO(rtenneti): Change the default 64 alignas value (used the default - // value from CACHELINE_SIZE). - ALIGNAS(64) char buffer[kMaxPacketSize]; - SerializedPacket serialized_packet = - packet_creator_.SerializePacket(buffer, kMaxPacketSize); - if (serialized_packet.packet == nullptr) { - LOG(DFATAL) << "Failed to SerializePacket. fec_policy:" << fec_send_policy_ - << " should_fec_protect_:" << should_fec_protect_; - delegate_->CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false); - return; - } - - // There may be AckListeners interested in this packet. - serialized_packet.listeners.swap(ack_listeners_); - ack_listeners_.clear(); - - delegate_->OnSerializedPacket(serialized_packet); - MaybeSendFecPacketAndCloseGroup(/*force=*/false, /*is_fec_timeout=*/false); - - // Maximum packet size may be only enacted while no packet is currently being - // constructed, so here we have a good opportunity to actually change it. - if (packet_creator_.CanSetMaxPacketLength()) { - packet_creator_.SetMaxPacketLength(max_packet_length_); - } - - // The packet has now been serialized, so the frames are no longer queued. - ack_queued_ = false; - stop_waiting_queued_ = false; -} - void QuicPacketGenerator::StopSendingVersion() { packet_creator_.StopSendingVersion(); } @@ -532,4 +494,31 @@ packet_creator_.SetEncrypter(level, encrypter); } +void QuicPacketGenerator::OnSerializedPacket( + SerializedPacket* serialized_packet) { + if (serialized_packet->packet == nullptr) { + LOG(DFATAL) << "Failed to SerializePacket. fec_policy:" << fec_send_policy_ + << " should_fec_protect_:" << should_fec_protect_; + delegate_->CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false); + return; + } + + // There may be AckListeners interested in this packet. + serialized_packet->listeners.swap(ack_listeners_); + ack_listeners_.clear(); + + delegate_->OnSerializedPacket(*serialized_packet); + MaybeSendFecPacketAndCloseGroup(/*force=*/false, /*is_fec_timeout=*/false); + + // Maximum packet size may be only enacted while no packet is currently being + // constructed, so here we have a good opportunity to actually change it. + if (packet_creator_.CanSetMaxPacketLength()) { + packet_creator_.SetMaxPacketLength(max_packet_length_); + } + + // The packet has now been serialized, so the frames are no longer queued. + ack_queued_ = false; + stop_waiting_queued_ = false; +} + } // namespace net
diff --git a/net/quic/quic_packet_generator.h b/net/quic/quic_packet_generator.h index 07ace040..194cb86 100644 --- a/net/quic/quic_packet_generator.h +++ b/net/quic/quic_packet_generator.h
@@ -65,7 +65,8 @@ class QuicPacketGeneratorPeer; } // namespace test -class NET_EXPORT_PRIVATE QuicPacketGenerator { +class NET_EXPORT_PRIVATE QuicPacketGenerator + : public QuicPacketCreator::DelegateInterface { public: class NET_EXPORT_PRIVATE DelegateInterface { public: @@ -98,7 +99,7 @@ QuicRandom* random_generator, DelegateInterface* delegate); - virtual ~QuicPacketGenerator(); + ~QuicPacketGenerator() override; // Called by the connection in the event of the congestion window changing. void OnCongestionWindowChange(QuicPacketCount max_packets_in_flight); @@ -183,6 +184,9 @@ // Sets the encrypter to use for the encryption level. void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter); + // QuicPacketCreator::DelegateInterface. + void OnSerializedPacket(SerializedPacket* serialized_packet) override; + // Sets the encryption level that will be applied to new packets. void set_encryption_level(EncryptionLevel level); @@ -256,14 +260,15 @@ // retransmittable) would still allow the resulting packet to be sent now. bool CanSendWithNextPendingFrameAddition() const; // Add exactly one pending frame, preferring ack frames over control frames. + // Returns true if a pending frame is successfully added. + // Returns false and flushes current open packet if the pending frame cannot + // fit into current open packet. bool AddNextPendingFrame(); // Adds a frame and takes ownership of the underlying buffer. bool AddFrame(const QuicFrame& frame, UniqueStreamBuffer buffer, bool needs_padding); - void SerializeAndSendPacket(); - DelegateInterface* delegate_; DebugDelegate* debug_delegate_;
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc index 0dcf229..2c9487a 100644 --- a/net/quic/quic_packet_generator_test.cc +++ b/net/quic/quic_packet_generator_test.cc
@@ -716,12 +716,14 @@ EXPECT_TRUE(generator_.HasQueuedFrames()); // This frame will not fit with the existing frame, causing the queued frame - // to be serialized, and it will not fit with another frame like it, so it is - // serialized by itself. + // to be serialized, and it will be added to a new open packet. consumed = generator_.ConsumeData(kHeadersStreamId, MakeIOVector("bar"), 3, true, MAY_FEC_PROTECT, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); + EXPECT_TRUE(generator_.HasQueuedFrames()); + + creator_->Flush(); EXPECT_FALSE(generator_.HasQueuedFrames()); PacketContents contents;
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index fe4e8b7..ec0aea66 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h
@@ -50,9 +50,6 @@ typedef uint32 QuicTag; typedef std::vector<QuicTag> QuicTagVector; typedef std::map<QuicTag, std::string> QuicTagValueMap; -// TODO(rtenneti): Didn't use SpdyPriority because SpdyPriority is uint8 and -// QuicPriority is uint32. Use SpdyPriority when we change the QUIC_VERSION. -typedef uint32 QuicPriority; typedef uint16 QuicPacketLength; // Default initial maximum size in bytes of a QUIC packet.
diff --git a/net/quic/quic_reliable_client_stream.cc b/net/quic/quic_reliable_client_stream.cc index 00132b6e..232962d 100644 --- a/net/quic/quic_reliable_client_stream.cc +++ b/net/quic/quic_reliable_client_stream.cc
@@ -70,11 +70,11 @@ } } -QuicPriority QuicReliableClientStream::EffectivePriority() const { +SpdyPriority QuicReliableClientStream::Priority() const { if (delegate_ && delegate_->HasSendHeadersComplete()) { - return QuicSpdyStream::EffectivePriority(); + return QuicSpdyStream::Priority(); } - return QuicWriteBlockedList::kHighestPriority; + return net::kHighestPriority; } int QuicReliableClientStream::WriteStreamData( @@ -126,7 +126,7 @@ bool QuicReliableClientStream::CanWrite(const CompletionCallback& callback) { bool can_write = session()->connection()->CanWrite(HAS_RETRANSMITTABLE_DATA); if (!can_write) { - session()->MarkConnectionLevelWriteBlocked(id(), EffectivePriority()); + session()->MarkConnectionLevelWriteBlocked(id(), Priority()); DCHECK(callback_.is_null()); callback_ = callback; }
diff --git a/net/quic/quic_reliable_client_stream.h b/net/quic/quic_reliable_client_stream.h index 8d7453b..bb0787f 100644 --- a/net/quic/quic_reliable_client_stream.h +++ b/net/quic/quic_reliable_client_stream.h
@@ -61,7 +61,7 @@ void OnDataAvailable() override; void OnClose() override; void OnCanWrite() override; - QuicPriority EffectivePriority() const override; + SpdyPriority Priority() const override; // While the server's set_priority shouldn't be called externally, the creator // of client-side streams should be able to set the priority.
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc index 2a325d6..0ef3169 100644 --- a/net/quic/quic_session.cc +++ b/net/quic/quic_session.cc
@@ -19,6 +19,7 @@ using std::max; using std::string; using std::vector; +using net::SpdyPriority; namespace net { @@ -112,8 +113,7 @@ perspective(), kMinimumFlowControlSendWindow, config_.GetInitialSessionFlowControlWindowToSend(), - false), - has_pending_handshake_(false) {} + false) {} void QuicSession::Initialize() { connection_->set_visitor(visitor_shim_.get()); @@ -258,12 +258,9 @@ return; } QuicStreamId stream_id = write_blocked_streams_.PopFront(); - if (stream_id == kCryptoStreamId) { - has_pending_handshake_ = false; // We just popped it. - } ReliableQuicStream* stream = GetStream(stream_id); if (stream != nullptr && !stream->flow_controller()->IsBlocked()) { - // If the stream can't write all bytes, it'll re-add itself to the blocked + // If the stream can't write all bytes it'll re-add itself to the blocked // list. stream->OnCanWrite(); } @@ -281,7 +278,7 @@ } bool QuicSession::HasPendingHandshake() const { - return has_pending_handshake_; + return write_blocked_streams_.crypto_stream_blocked(); } bool QuicSession::HasOpenDynamicStreams() const { @@ -295,8 +292,10 @@ bool fin, FecProtection fec_protection, QuicAckListenerInterface* ack_notifier_delegate) { - return connection_->SendStreamData(id, iov, offset, fin, fec_protection, - ack_notifier_delegate); + QuicConsumedData data = connection_->SendStreamData( + id, iov, offset, fin, fec_protection, ack_notifier_delegate); + write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed); + return data; } void QuicSession::SendRstStream(QuicStreamId id, @@ -712,31 +711,18 @@ } size_t QuicSession::GetNumOpenStreams() const { - if (FLAGS_quic_count_unfinished_as_open_streams) { - if (FLAGS_allow_many_available_streams) { - return dynamic_stream_map_.size() - draining_streams_.size() + - locally_closed_streams_highest_offset_.size(); - } else { - return dynamic_stream_map_.size() + available_streams_.size() - - draining_streams_.size() + - locally_closed_streams_highest_offset_.size(); - } + if (FLAGS_allow_many_available_streams) { + return dynamic_stream_map_.size() - draining_streams_.size() + + locally_closed_streams_highest_offset_.size(); } else { - if (FLAGS_allow_many_available_streams) { - return dynamic_stream_map_.size() - draining_streams_.size(); - } else { - return dynamic_stream_map_.size() + available_streams_.size() - - draining_streams_.size(); - } + return dynamic_stream_map_.size() + available_streams_.size() - + draining_streams_.size() + + locally_closed_streams_highest_offset_.size(); } } size_t QuicSession::GetNumActiveStreams() const { - if (FLAGS_quic_count_unfinished_as_open_streams) { - return GetNumOpenStreams() - locally_closed_streams_highest_offset_.size(); - } else { - return GetNumOpenStreams(); - } + return GetNumOpenStreams() - locally_closed_streams_highest_offset_.size(); } size_t QuicSession::GetNumAvailableStreams() const { @@ -744,28 +730,20 @@ } void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id, - QuicPriority priority) { + SpdyPriority priority) { #ifndef NDEBUG ReliableQuicStream* stream = GetStream(id); if (stream != nullptr) { - LOG_IF(DFATAL, priority != stream->EffectivePriority()) + LOG_IF(DFATAL, priority != stream->Priority()) << ENDPOINT << "Stream " << id - << "Priorities do not match. Got: " << priority - << " Expected: " << stream->EffectivePriority(); + << "Priorities do not match. Got: " << static_cast<int>(priority) + << " Expected: " << static_cast<int>(stream->Priority()); } else { LOG(DFATAL) << "Marking unknown stream " << id << " blocked."; } #endif - if (id == kCryptoStreamId) { - DCHECK(!has_pending_handshake_); - has_pending_handshake_ = true; - // TODO(jar): Be sure to use the highest priority for the crypto stream, - // perhaps by adding a "special" priority for it that is higher than - // kHighestPriority. - priority = kHighestPriority; - } - write_blocked_streams_.PushBack(id, priority); + write_blocked_streams_.AddStream(id, priority); } bool QuicSession::HasDataToWrite() const { @@ -776,12 +754,7 @@ void QuicSession::PostProcessAfterData() { STLDeleteElements(&closed_streams_); - - // A buggy client may fail to send FIN/RSTs. Don't tolerate this. - if (!FLAGS_quic_count_unfinished_as_open_streams && - locally_closed_streams_highest_offset_.size() > max_open_streams_) { - CloseConnection(QUIC_TOO_MANY_UNFINISHED_STREAMS); - } + closed_streams_.clear(); } bool QuicSession::IsConnectionFlowControlBlocked() const {
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h index cbdfb05..00d446ad 100644 --- a/net/quic/quic_session.h +++ b/net/quic/quic_session.h
@@ -168,7 +168,7 @@ // connection-level flow control but not by its own stream-level flow control. // The stream will be given a chance to write when a connection-level // WINDOW_UPDATE arrives. - void MarkConnectionLevelWriteBlocked(QuicStreamId id, QuicPriority priority); + void MarkConnectionLevelWriteBlocked(QuicStreamId id, SpdyPriority priority); // Returns true if the session has data to be sent, either queued in the // connection, or in a write-blocked stream. @@ -335,9 +335,6 @@ // Used for connection-level flow control. QuicFlowController flow_controller_; - // Indicate if there is pending data for the crypto stream. - bool has_pending_handshake_; - DISALLOW_COPY_AND_ASSIGN(QuicSession); };
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc index 6d29f23..8c57679 100644 --- a/net/quic/quic_session_test.cc +++ b/net/quic/quic_session_test.cc
@@ -36,6 +36,7 @@ using std::string; using std::vector; using testing::CreateFunctor; +using net::SpdyPriority; using testing::InSequence; using testing::Invoke; using testing::Return; @@ -46,8 +47,8 @@ namespace test { namespace { -const QuicPriority kHighestPriority = 0; -const QuicPriority kSomeMiddlePriority = 3; +const SpdyPriority kHighestPriority = 0; +const SpdyPriority kSomeMiddlePriority = 3; class TestCryptoStream : public QuicCryptoStream { public: @@ -96,6 +97,8 @@ WriteOrBufferData(data, fin, nullptr); } + using QuicSpdyStream::set_priority; + MOCK_METHOD0(OnCanWrite, void()); }; @@ -111,6 +114,10 @@ session_->MarkConnectionLevelWriteBlocked(stream_id_, kSomeMiddlePriority); } + void MarkHighPriorityWriteBlocked() { + session_->MarkConnectionLevelWriteBlocked(stream_id_, kHighestPriority); + } + private: QuicSession* const session_; const QuicStreamId stream_id_; @@ -158,13 +165,14 @@ bool fin, FecProtection fec_protection, QuicAckListenerInterface* ack_notifier_delegate) override { - // Always consumes everything. - if (writev_consumes_all_data_) { - return QuicConsumedData(data.total_length, fin); - } else { - return QuicSession::WritevData(id, data, offset, fin, fec_protection, - ack_notifier_delegate); + QuicConsumedData consumed(data.total_length, fin); + if (!writev_consumes_all_data_) { + consumed = QuicSession::WritevData(id, data, offset, fin, fec_protection, + ack_notifier_delegate); } + QuicSessionPeer::GetWriteBlockedStreams(this) + ->UpdateBytesForStream(id, consumed.bytes_consumed); + return consumed; } void set_writev_consumes_all_data(bool val) { @@ -177,6 +185,15 @@ MAY_FEC_PROTECT, nullptr); } + QuicConsumedData SendLargeFakeData(QuicStreamId id, int bytes) { + DCHECK(writev_consumes_all_data_); + struct iovec iov; + iov.iov_base = nullptr; // should not be read. + iov.iov_len = static_cast<size_t>(bytes); + return WritevData(id, QuicIOVector(&iov, 1, bytes), 0, true, + MAY_FEC_PROTECT, nullptr); + } + using QuicSession::PostProcessAfterData; private: @@ -370,10 +387,10 @@ TEST_P(QuicSessionTestServer, DebugDFatalIfMarkWriteBlockedCalledWithWrongPriority) { - const QuicPriority kDifferentPriority = 0; + const SpdyPriority kDifferentPriority = 0; TestStream* stream2 = session_.CreateOutgoingDynamicStream(); - EXPECT_NE(kDifferentPriority, stream2->EffectivePriority()); + EXPECT_NE(kDifferentPriority, stream2->Priority()); EXPECT_DEBUG_DFATAL(session_.MarkConnectionLevelWriteBlocked( stream2->id(), kDifferentPriority), "Priorities do not match. Got: 0 Expected: 3"); @@ -390,16 +407,109 @@ InSequence s; StreamBlocker stream2_blocker(&session_, stream2->id()); - // Reregister, to test the loop limit. - EXPECT_CALL(*stream2, OnCanWrite()) - .WillOnce(Invoke(&stream2_blocker, - &StreamBlocker::MarkConnectionLevelWriteBlocked)); - EXPECT_CALL(*stream6, OnCanWrite()); - EXPECT_CALL(*stream4, OnCanWrite()); + + if (FLAGS_quic_batch_writes) { + // Reregister, to test the loop limit. + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked)); + // 2 will get called a second time as it didn't finish its block + EXPECT_CALL(*stream2, OnCanWrite()); + EXPECT_CALL(*stream6, OnCanWrite()); + // 4 will not get called, as we exceeded the loop limit. + } else { + // Reregister, to test the loop limit. + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked)); + EXPECT_CALL(*stream6, OnCanWrite()); + EXPECT_CALL(*stream4, OnCanWrite()); + } session_.OnCanWrite(); EXPECT_TRUE(session_.WillingAndAbleToWrite()); } +TEST_P(QuicSessionTestServer, TestBatchedWrites) { + FLAGS_quic_batch_writes = true; + TestStream* stream2 = session_.CreateOutgoingDynamicStream(); + TestStream* stream4 = session_.CreateOutgoingDynamicStream(); + TestStream* stream6 = session_.CreateOutgoingDynamicStream(); + + session_.set_writev_consumes_all_data(true); + session_.MarkConnectionLevelWriteBlocked(stream2->id(), kSomeMiddlePriority); + session_.MarkConnectionLevelWriteBlocked(stream4->id(), kSomeMiddlePriority); + + StreamBlocker stream2_blocker(&session_, stream2->id()); + StreamBlocker stream4_blocker(&session_, stream4->id()); + StreamBlocker stream6_blocker(&session_, stream6->id()); + // With two sessions blocked, we should get two write calls. They should both + // go to the first stream as it will only write 6k and mark itself blocked + // again. + InSequence s; + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, + stream2->id(), 6000))), + Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, + stream2->id(), 6000))), + Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); + session_.OnCanWrite(); + + // We should get one more call for stream2, at which point it has used its + // write quota and we move over to stream 4. + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, + stream2->id(), 6000))), + Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); + EXPECT_CALL(*stream4, OnCanWrite()) + .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, + stream4->id(), 6000))), + Invoke(&stream4_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); + session_.OnCanWrite(); + + // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high + // priority stream 6. 4 should be preempted. 6 will write but *not* block so + // will cede back to 4. + stream6->set_priority(kHighestPriority); + EXPECT_CALL(*stream4, OnCanWrite()) + .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, + stream4->id(), 6000))), + Invoke(&stream4_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked), + Invoke(&stream6_blocker, + &StreamBlocker::MarkHighPriorityWriteBlocked))); + EXPECT_CALL(*stream6, OnCanWrite()) + .WillOnce(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, stream4->id(), 6000)))); + session_.OnCanWrite(); + + // Stream4 alread did 6k worth of writes, so after doing another 12k it should + // cede and 2 should resume. + EXPECT_CALL(*stream4, OnCanWrite()) + .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, + stream4->id(), 12000))), + Invoke(&stream4_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(DoAll(testing::IgnoreResult(Invoke(CreateFunctor( + &session_, &TestSession::SendLargeFakeData, + stream2->id(), 6000))), + Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); + session_.OnCanWrite(); +} + TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) { // Drive congestion control manually. MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>; @@ -516,13 +626,8 @@ TestCryptoStream* crypto_stream = session_.GetCryptoStream(); EXPECT_CALL(*crypto_stream, OnCanWrite()); - // Re-register all other streams, to show they weren't able to proceed. - EXPECT_CALL(*stream2, OnCanWrite()) - .WillOnce(Invoke(&stream2_blocker, - &StreamBlocker::MarkConnectionLevelWriteBlocked)); - EXPECT_CALL(*stream3, OnCanWrite()) - .WillOnce(Invoke(&stream3_blocker, - &StreamBlocker::MarkConnectionLevelWriteBlocked)); + EXPECT_CALL(*stream2, OnCanWrite()); + EXPECT_CALL(*stream3, OnCanWrite()); EXPECT_CALL(*stream4, OnCanWrite()) .WillOnce(Invoke(&stream4_blocker, &StreamBlocker::MarkConnectionLevelWriteBlocked)); @@ -969,36 +1074,7 @@ EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); } -TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseConnectionClose) { - FLAGS_quic_count_unfinished_as_open_streams = false; - // If a buggy/malicious peer creates too many streams that are not ended - // with a FIN or RST then we send a connection close. - EXPECT_CALL(*connection_, - SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS)); - - const QuicStreamId kMaxStreams = 5; - QuicSessionPeer::SetMaxOpenStreams(&session_, kMaxStreams); - - // Create kMaxStreams + 1 data streams, and close them all without receiving - // a FIN or a RST_STREAM from the client. - const QuicStreamId kFirstStreamId = kClientDataStreamId1; - const QuicStreamId kFinalStreamId = - kClientDataStreamId1 + 2 * kMaxStreams + 1; - for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) { - QuicStreamFrame data1(i, false, 0, StringPiece("HT")); - session_.OnStreamFrame(data1); - EXPECT_EQ(1u, session_.GetNumOpenStreams()); - EXPECT_CALL(*connection_, SendRstStream(i, _, _)); - session_.CloseStream(i); - } - - // Called after any new data is received by the session, and triggers the - // call to close the connection. - session_.PostProcessAfterData(); -} - TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) { - FLAGS_quic_count_unfinished_as_open_streams = true; // If a buggy/malicious peer creates too many streams that are not ended // with a FIN or RST then we send a connection close or an RST to // refuse streams. @@ -1038,20 +1114,13 @@ // Verify that a draining stream (which has received a FIN but not consumed // it) does not count against the open quota (because it is closed from the // protocol point of view). - if (FLAGS_quic_count_unfinished_as_open_streams) { - if (GetParam() <= QUIC_VERSION_27) { - EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)) - .Times(0); - } else { - EXPECT_CALL(*connection_, SendRstStream(_, QUIC_REFUSED_STREAM, _)) - .Times(0); - } + if (GetParam() <= QUIC_VERSION_27) { + EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)) + .Times(0); } else { - EXPECT_CALL(*connection_, - SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS)) + EXPECT_CALL(*connection_, SendRstStream(_, QUIC_REFUSED_STREAM, _)) .Times(0); } - const QuicStreamId kMaxStreams = 5; QuicSessionPeer::SetMaxOpenStreams(&session_, kMaxStreams);
diff --git a/net/quic/quic_spdy_session.cc b/net/quic/quic_spdy_session.cc index ca0e67f..b33094a 100644 --- a/net/quic/quic_spdy_session.cc +++ b/net/quic/quic_spdy_session.cc
@@ -42,7 +42,7 @@ } void QuicSpdySession::OnStreamHeadersPriority(QuicStreamId stream_id, - QuicPriority priority) { + SpdyPriority priority) { QuicSpdyStream* stream = GetSpdyDataStream(stream_id); if (!stream) { // It's quite possible to receive headers after a stream has been reset. @@ -66,7 +66,7 @@ QuicStreamId id, const SpdyHeaderBlock& headers, bool fin, - QuicPriority priority, + SpdyPriority priority, QuicAckListenerInterface* ack_notifier_delegate) { return headers_stream_->WriteHeaders(id, headers, fin, priority, ack_notifier_delegate);
diff --git a/net/quic/quic_spdy_session.h b/net/quic/quic_spdy_session.h index 6f7b4a0..3b5c187 100644 --- a/net/quic/quic_spdy_session.h +++ b/net/quic/quic_spdy_session.h
@@ -31,7 +31,7 @@ // received for this stream. This method will only be called for server // streams. virtual void OnStreamHeadersPriority(QuicStreamId stream_id, - QuicPriority priority); + SpdyPriority priority); // Called by |headers_stream_| when headers have been completely received // for a stream. |fin| will be true if the fin flag was set in the headers // frame. @@ -46,7 +46,7 @@ size_t WriteHeaders(QuicStreamId id, const SpdyHeaderBlock& headers, bool fin, - QuicPriority priority, + SpdyPriority priority, QuicAckListenerInterface* ack_notifier_delegate); QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
diff --git a/net/quic/quic_spdy_stream.cc b/net/quic/quic_spdy_stream.cc index 775348f..8387d7f 100644 --- a/net/quic/quic_spdy_stream.cc +++ b/net/quic/quic_spdy_stream.cc
@@ -11,6 +11,7 @@ using base::StringPiece; using std::min; +using net::SpdyPriority; namespace net { @@ -24,7 +25,7 @@ // to set a priority client-side, or cancel a stream before stripping the // priority from the wire server-side. In either case, start out with a // priority in the middle. -QuicPriority kDefaultPriority = 3; +SpdyPriority kDefaultPriority = 3; } // namespace @@ -112,12 +113,12 @@ } } -void QuicSpdyStream::set_priority(QuicPriority priority) { +void QuicSpdyStream::set_priority(SpdyPriority priority) { DCHECK_EQ(0u, stream_bytes_written()); priority_ = priority; } -QuicPriority QuicSpdyStream::EffectivePriority() const { +SpdyPriority QuicSpdyStream::Priority() const { return priority(); } @@ -125,7 +126,7 @@ headers_data.AppendToString(&decompressed_headers_); } -void QuicSpdyStream::OnStreamHeadersPriority(QuicPriority priority) { +void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) { DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective()); set_priority(priority); }
diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h index 543e490..e55d6aa 100644 --- a/net/quic/quic_spdy_stream.h +++ b/net/quic/quic_spdy_stream.h
@@ -62,11 +62,9 @@ // ReliableQuicStream implementation void OnClose() override; - // By default, this is the same as priority(), however it allows streams - // to temporarily alter effective priority. For example if a SPDY stream has - // compressed but not written headers it can write the headers with a higher - // priority. - QuicPriority EffectivePriority() const override; + // This is the same as priority() and is being deprecated + // TODO(alyssar) remove after Priority refactor. + SpdyPriority Priority() const override; // Called by the session when decompressed headers data is received // for this stream. @@ -76,7 +74,7 @@ // Called by the session when headers with a priority have been received // for this stream. This method will only be called for server streams. - virtual void OnStreamHeadersPriority(QuicPriority priority); + virtual void OnStreamHeadersPriority(SpdyPriority priority); // Called by the session when decompressed headers have been completely // delilvered to this stream. If |fin| is true, then this stream @@ -115,13 +113,12 @@ return decompressed_headers_; } + SpdyPriority priority() const { return priority_; } + protected: // Sets priority_ to priority. This should only be called before bytes are // written to the server. - void set_priority(QuicPriority priority); - // This is protected because external classes should use EffectivePriority - // instead. - QuicPriority priority() const { return priority_; } + void set_priority(SpdyPriority priority); bool FinishedReadingHeaders() const; @@ -136,7 +133,7 @@ // True if the headers have been completely decompressed. bool headers_decompressed_; // The priority of the stream, once parsed. - QuicPriority priority_; + SpdyPriority priority_; // Contains a copy of the decompressed headers until they are consumed // via ProcessData or Readv. std::string decompressed_headers_;
diff --git a/net/quic/quic_spdy_stream_test.cc b/net/quic/quic_spdy_stream_test.cc index 75c5238..4e7f307 100644 --- a/net/quic/quic_spdy_stream_test.cc +++ b/net/quic/quic_spdy_stream_test.cc
@@ -18,6 +18,8 @@ using base::StringPiece; using std::min; using std::string; +using net::kHighestPriority; +using net::SpdyHeaderBlock; using testing::Return; using testing::StrictMock; using testing::_; @@ -120,12 +122,13 @@ Initialize(kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); - stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority()); + stream_->OnStreamHeadersPriority(net::kHighestPriority); stream_->OnStreamHeaders(headers); EXPECT_EQ("", stream_->data()); EXPECT_EQ(headers, stream_->decompressed_headers()); stream_->OnStreamHeadersComplete(false, headers.size()); - EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority()); + EXPECT_EQ(net::kHighestPriority, stream_->Priority()); + EXPECT_EQ(net::kHighestPriority, stream_->Priority()); EXPECT_EQ("", stream_->data()); EXPECT_EQ(headers, stream_->decompressed_headers()); EXPECT_FALSE(stream_->IsDoneReading()); @@ -135,12 +138,13 @@ Initialize(kShouldProcessData); string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); - stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority()); + stream_->OnStreamHeadersPriority(net::kHighestPriority); stream_->OnStreamHeaders(headers); EXPECT_EQ("", stream_->data()); EXPECT_EQ(headers, stream_->decompressed_headers()); stream_->OnStreamHeadersComplete(true, headers.size()); - EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority()); + EXPECT_EQ(net::kHighestPriority, stream_->Priority()); + EXPECT_EQ(net::kHighestPriority, stream_->Priority()); EXPECT_EQ("", stream_->data()); EXPECT_EQ(headers, stream_->decompressed_headers()); EXPECT_FALSE(stream_->IsDoneReading());
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc index 7a16115..95dfff92 100644 --- a/net/quic/quic_stream_sequencer_test.cc +++ b/net/quic/quic_stream_sequencer_test.cc
@@ -49,9 +49,7 @@ void(QuicErrorCode error, const string& details)); MOCK_METHOD1(Reset, void(QuicRstStreamErrorCode error)); MOCK_METHOD0(OnCanWrite, void()); - QuicPriority EffectivePriority() const override { - return QuicUtils::HighestPriority(); - } + SpdyPriority Priority() const override { return net::kHighestPriority; } virtual bool IsFlowControlEnabled() const { return true; } };
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc index b821633..89354f1 100644 --- a/net/quic/quic_utils.cc +++ b/net/quic/quic_utils.cc
@@ -343,9 +343,4 @@ return s; } -// static -QuicPriority QuicUtils::HighestPriority() { - return QuicWriteBlockedList::kHighestPriority; -} - } // namespace net
diff --git a/net/quic/quic_utils.h b/net/quic/quic_utils.h index fb379e6..017ad46 100644 --- a/net/quic/quic_utils.h +++ b/net/quic/quic_utils.h
@@ -95,8 +95,6 @@ return reinterpret_cast<char*>(data); } - static QuicPriority HighestPriority(); - private: DISALLOW_COPY_AND_ASSIGN(QuicUtils); };
diff --git a/net/quic/quic_write_blocked_list.cc b/net/quic/quic_write_blocked_list.cc index e763d17..0a747724 100644 --- a/net/quic/quic_write_blocked_list.cc +++ b/net/quic/quic_write_blocked_list.cc
@@ -6,13 +6,14 @@ namespace net { -const QuicPriority QuicWriteBlockedList::kHighestPriority = - static_cast<QuicPriority>(net::kHighestPriority); -const QuicPriority QuicWriteBlockedList::kLowestPriority = - static_cast<QuicPriority>(net::kLowestPriority); - QuicWriteBlockedList::QuicWriteBlockedList() - : crypto_stream_blocked_(false), headers_stream_blocked_(false) { + : last_priority_popped_(0), + crypto_stream_blocked_(false), + headers_stream_blocked_(false) { + memset(batch_write_stream_id_, 0, + arraysize(batch_write_stream_id_) * sizeof(QuicStreamId)); + memset(bytes_left_for_batch_write_, 0, + arraysize(bytes_left_for_batch_write_) * sizeof(int32)); } QuicWriteBlockedList::~QuicWriteBlockedList() {}
diff --git a/net/quic/quic_write_blocked_list.h b/net/quic/quic_write_blocked_list.h index 3c08badd..f68c7e7 100644 --- a/net/quic/quic_write_blocked_list.h +++ b/net/quic/quic_write_blocked_list.h
@@ -8,6 +8,7 @@ #include <set> #include "net/base/net_export.h" +#include "net/quic/quic_flags.h" #include "net/quic/quic_protocol.h" #include "net/spdy/write_blocked_list.h" @@ -21,9 +22,6 @@ typedef WriteBlockedList<QuicStreamId> QuicWriteBlockedListBase; public: - static const QuicPriority kHighestPriority; - static const QuicPriority kLowestPriority; - QuicWriteBlockedList(); ~QuicWriteBlockedList(); @@ -47,6 +45,8 @@ return num_blocked; } + // Pops the highest priorty stream, special casing crypto and headers streams. + // Latches the most recently popped data stream for batch writing purposes. QuicStreamId PopFront() { if (crypto_stream_blocked_) { crypto_stream_blocked_ = false; @@ -61,26 +61,67 @@ SpdyPriority priority = base_write_blocked_list_.GetHighestPriorityWriteBlockedList(); QuicStreamId id = base_write_blocked_list_.PopFront(priority); + + if (base_write_blocked_list_.NumBlockedStreams(priority) == 0) { + // If no streams are blocked, don't bother latching. This stream will be + // the first popped for its priority anyway. + batch_write_stream_id_[priority] = 0; + last_priority_popped_ = priority; + } else if (batch_write_stream_id_[priority] != id) { + // If newly latching this batch write stream, let it write 16k. + batch_write_stream_id_[priority] = id; + bytes_left_for_batch_write_[priority] = 16000; + last_priority_popped_ = priority; + } + return id; } - void PushBack(QuicStreamId stream_id, QuicPriority priority) { + void UpdateBytesForStream(QuicStreamId stream_id, size_t bytes) { + if (batch_write_stream_id_[last_priority_popped_] == stream_id) { + // If this was the last data stream popped by PopFront, update the + // bytes remaining in its batch write. + bytes_left_for_batch_write_[last_priority_popped_] -= + static_cast<int32>(bytes); + } else { + // If a batch write stream was set, it should only be preempted by the + // crypto or headers streams. Any higher priority data stream would + // *become* the new batch write stream. + if (FLAGS_quic_respect_send_alarm && FLAGS_quic_batch_writes) { + DCHECK(stream_id == kCryptoStreamId || stream_id == kHeadersStreamId || + batch_write_stream_id_[last_priority_popped_] == 0 || + bytes == 0); + } + } + } + + // Pushes a stream to the back of the std::list for this priority level + // *unless* it is latched for doing batched writes in which case it goes to + // the front of the std::list for this priority level. + // Headers and crypto streams are special cased to always resume first. + void AddStream(QuicStreamId stream_id, SpdyPriority priority) { if (stream_id == kCryptoStreamId) { - DCHECK_EQ(kHighestPriority, priority); + DCHECK_EQ(net::kHighestPriority, priority); // TODO(avd) Add DCHECK(!crypto_stream_blocked_) crypto_stream_blocked_ = true; return; } if (stream_id == kHeadersStreamId) { - DCHECK_EQ(kHighestPriority, priority); + DCHECK_EQ(net::kHighestPriority, priority); // TODO(avd) Add DCHECK(!headers_stream_blocked_); headers_stream_blocked_ = true; return; } - - base_write_blocked_list_.PushBack( - stream_id, static_cast<SpdyPriority>(priority)); + if (FLAGS_quic_batch_writes && + stream_id == batch_write_stream_id_[last_priority_popped_] && + bytes_left_for_batch_write_[last_priority_popped_] > 0) { + // If the batch write stream has more data to write, push it to the front + // for its priority level. + base_write_blocked_list_.PushFront(stream_id, priority); + } else { + base_write_blocked_list_.PushBack(stream_id, priority); + } return; } @@ -89,6 +130,19 @@ private: QuicWriteBlockedListBase base_write_blocked_list_; + + // If performing batch writes, this will be the stream ID of the stream doing + // batch writes for this priority level. We will allow this stream to write + // until it has written kBatchWriteSize bytes, it has no more data to write, + // or a higher priority stream preempts. + QuicStreamId batch_write_stream_id_[kLowestPriority + 1]; + // Set to kBatchWriteSize when we set a new batch_write_stream_id_ for a given + // priority. This is decremented with each write the stream does until it is + // done with its batch write. + int32 bytes_left_for_batch_write_[kLowestPriority + 1]; + // Tracks the last priority popped for UpdateBytesForStream. + SpdyPriority last_priority_popped_; + bool crypto_stream_blocked_; bool headers_stream_blocked_;
diff --git a/net/quic/quic_write_blocked_list_test.cc b/net/quic/quic_write_blocked_list_test.cc index 0633f63..827f971 100644 --- a/net/quic/quic_write_blocked_list_test.cc +++ b/net/quic/quic_write_blocked_list_test.cc
@@ -7,6 +7,12 @@ #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" +using net::kLowestPriority; +using net::kHighestPriority; + +using net::kLowestPriority; +using net::kHighestPriority; + namespace net { namespace test { namespace { @@ -16,16 +22,11 @@ // Mark streams blocked in roughly reverse priority order, and // verify that streams are sorted. - write_blocked_list.PushBack(40, - QuicWriteBlockedList::kLowestPriority); - write_blocked_list.PushBack(23, - QuicWriteBlockedList::kHighestPriority); - write_blocked_list.PushBack(17, - QuicWriteBlockedList::kHighestPriority); - write_blocked_list.PushBack(kHeadersStreamId, - QuicWriteBlockedList::kHighestPriority); - write_blocked_list.PushBack(kCryptoStreamId, - QuicWriteBlockedList::kHighestPriority); + write_blocked_list.AddStream(40, net::kLowestPriority); + write_blocked_list.AddStream(23, net::kHighestPriority); + write_blocked_list.AddStream(17, net::kHighestPriority); + write_blocked_list.AddStream(kHeadersStreamId, net::kHighestPriority); + write_blocked_list.AddStream(kCryptoStreamId, net::kHighestPriority); EXPECT_EQ(5u, write_blocked_list.NumBlockedStreams()); EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); @@ -47,8 +48,7 @@ TEST(QuicWriteBlockedListTest, CryptoStream) { QuicWriteBlockedList write_blocked_list; - write_blocked_list.PushBack(kCryptoStreamId, - QuicWriteBlockedList::kHighestPriority); + write_blocked_list.AddStream(kCryptoStreamId, net::kHighestPriority); EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); @@ -59,8 +59,7 @@ TEST(QuicWriteBlockedListTest, HeadersStream) { QuicWriteBlockedList write_blocked_list; - write_blocked_list.PushBack(kHeadersStreamId, - QuicWriteBlockedList::kHighestPriority); + write_blocked_list.AddStream(kHeadersStreamId, net::kHighestPriority); EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); @@ -71,10 +70,8 @@ TEST(QuicWriteBlockedListTest, VerifyHeadersStream) { QuicWriteBlockedList write_blocked_list; - write_blocked_list.PushBack(5, - QuicWriteBlockedList::kHighestPriority); - write_blocked_list.PushBack(kHeadersStreamId, - QuicWriteBlockedList::kHighestPriority); + write_blocked_list.AddStream(5, net::kHighestPriority); + write_blocked_list.AddStream(kHeadersStreamId, net::kHighestPriority); EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); @@ -95,12 +92,9 @@ // Try to add a stream to the write blocked list multiple times at the same // priority. const QuicStreamId kBlockedId = kClientDataStreamId1; - write_blocked_list.PushBack(kBlockedId, - QuicWriteBlockedList::kHighestPriority); - write_blocked_list.PushBack(kBlockedId, - QuicWriteBlockedList::kHighestPriority); - write_blocked_list.PushBack(kBlockedId, - QuicWriteBlockedList::kHighestPriority); + write_blocked_list.AddStream(kBlockedId, net::kHighestPriority); + write_blocked_list.AddStream(kBlockedId, net::kHighestPriority); + write_blocked_list.AddStream(kBlockedId, net::kHighestPriority); // This should only result in one blocked stream being added. EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); @@ -112,6 +106,60 @@ EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); } +TEST(QuicWriteBlockedListTest, BatchingWrites) { + FLAGS_quic_batch_writes = true; + QuicWriteBlockedList write_blocked_list; + + const QuicStreamId id1 = kClientDataStreamId1; + const QuicStreamId id2 = kClientDataStreamId2; + + write_blocked_list.AddStream(id1, net::kLowestPriority); + write_blocked_list.AddStream(id2, net::kLowestPriority); + EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); + + // The first stream we push back should stay at the front until 16k is + // written. + EXPECT_EQ(id1, write_blocked_list.PopFront()); + write_blocked_list.AddStream(id1, net::kHighestPriority); + write_blocked_list.UpdateBytesForStream(id1, 15999); + write_blocked_list.AddStream(id1, net::kLowestPriority); + EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); + EXPECT_EQ(id1, write_blocked_list.PopFront()); + + // Once 16k is written the first stream will cede to the next. + write_blocked_list.AddStream(id1, net::kHighestPriority); + write_blocked_list.UpdateBytesForStream(id1, 1); + write_blocked_list.AddStream(id1, net::kLowestPriority); + EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); + EXPECT_EQ(id2, write_blocked_list.PopFront()); + + // Set the new stream to have written all but one byte. + write_blocked_list.AddStream(id2, net::kHighestPriority); + write_blocked_list.UpdateBytesForStream(id2, 15999); + write_blocked_list.AddStream(id2, net::kLowestPriority); + EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); + + // Ensure higher priority streams are popped first. + const QuicStreamId id3 = kClientDataStreamId2 + 2; + write_blocked_list.AddStream(id3, net::kHighestPriority); + EXPECT_EQ(id3, write_blocked_list.PopFront()); + + // Higher priority streams will always be popped first, even if using their + // byte quota + write_blocked_list.UpdateBytesForStream(id3, 20000); + write_blocked_list.AddStream(id3, net::kHighestPriority); + EXPECT_EQ(id3, write_blocked_list.PopFront()); + + // Once the higher priority stream is out of the way, id2 will resume its 16k + // write, with only 1 byte remaining of its guaranteed write allocation. + EXPECT_EQ(id2, write_blocked_list.PopFront()); + write_blocked_list.AddStream(id2, net::kHighestPriority); + write_blocked_list.UpdateBytesForStream(id2, 1); + write_blocked_list.AddStream(id2, net::kLowestPriority); + EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); + EXPECT_EQ(id1, write_blocked_list.PopFront()); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc index 1efad19..8389c0fb 100644 --- a/net/quic/reliable_quic_stream.cc +++ b/net/quic/reliable_quic_stream.cc
@@ -277,7 +277,7 @@ // WINDOW_UPDATE arrives. if (connection_flow_controller_->IsBlocked() && !flow_controller_.IsBlocked()) { - session_->MarkConnectionLevelWriteBlocked(id(), EffectivePriority()); + session_->MarkConnectionLevelWriteBlocked(id(), Priority()); } } @@ -325,6 +325,12 @@ AddBytesSent(consumed_data.bytes_consumed); + // The write may have generated a write error causing this stream to be + // closed. If so, simply return without marking the stream write blocked. + if (write_side_closed_) { + return consumed_data; + } + if (consumed_data.bytes_consumed == write_length) { if (!fin_with_zero_data) { MaybeSendBlocked(); @@ -336,10 +342,10 @@ } CloseWriteSide(); } else if (fin && !consumed_data.fin_consumed) { - session_->MarkConnectionLevelWriteBlocked(id(), EffectivePriority()); + session_->MarkConnectionLevelWriteBlocked(id(), Priority()); } } else { - session_->MarkConnectionLevelWriteBlocked(id(), EffectivePriority()); + session_->MarkConnectionLevelWriteBlocked(id(), Priority()); } return consumed_data; }
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h index ab36df0..096770c 100644 --- a/net/quic/reliable_quic_stream.h +++ b/net/quic/reliable_quic_stream.h
@@ -31,6 +31,10 @@ #include "net/quic/quic_protocol.h" #include "net/quic/quic_stream_sequencer.h" #include "net/quic/quic_types.h" +//#include "std::strings/std::stringpiece.h" +//#include "util/refcount/reffed_ptr.h" +// TODO(alyssar) remove this after cleaning Priority logic from this class. +#include "net/quic/quic_write_blocked_list.h" namespace net { @@ -91,9 +95,8 @@ virtual void CloseConnectionWithDetails(QuicErrorCode error, const std::string& details); - // Returns the effective priority for the stream. This value may change - // during the life of the stream. - virtual QuicPriority EffectivePriority() const = 0; + // Returns the priority for the stream. + virtual SpdyPriority Priority() const = 0; QuicStreamId id() const { return id_; }
diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc index 46a3fff5..03442b3 100644 --- a/net/quic/reliable_quic_stream_test.cc +++ b/net/quic/reliable_quic_stream_test.cc
@@ -27,6 +27,7 @@ using testing::CreateFunctor; using testing::InSequence; using testing::Invoke; +using testing::DoAll; using testing::Return; using testing::StrictMock; using testing::WithArgs; @@ -59,9 +60,7 @@ return should_process_data_ ? data_len : 0; } - QuicPriority EffectivePriority() const override { - return QuicUtils::HighestPriority(); - } + SpdyPriority Priority() const override { return net::kHighestPriority; } using ReliableQuicStream::WriteOrBufferData; using ReliableQuicStream::CloseWriteSide; @@ -140,6 +139,17 @@ write_blocked_list_->HasWriteBlockedDataStreams(); } + QuicConsumedData CloseStreamOnWriteError( + QuicStreamId id, + QuicIOVector /*iov*/, + QuicStreamOffset /*offset*/, + bool /*fin*/, + FecProtection /*fec_protection*/, + QuicAckListenerInterface* /*ack_notifier_delegate*/) { + session_->CloseStream(id); + return QuicConsumedData(1, false); + } + protected: MockConnectionHelper helper_; MockConnection* connection_; @@ -211,6 +221,18 @@ ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); } +TEST_F(ReliableQuicStreamTest, CloseOnPartialWrite) { + Initialize(kShouldProcessData); + + // Write some data and no fin. However, while writing the data + // close the stream and verify that MarkConnectionLevelWriteBlocked does not + // crash with an unknown stream. + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) + .WillOnce(Invoke(this, &ReliableQuicStreamTest::CloseStreamOnWriteError)); + stream_->WriteOrBufferData(StringPiece(kData1, 2), false, nullptr); + ASSERT_EQ(0u, write_blocked_list_->NumBlockedStreams()); +} + TEST_F(ReliableQuicStreamTest, WriteOrBufferData) { Initialize(kShouldProcessData);
diff --git a/net/quic/test_tools/quic_packet_creator_peer.cc b/net/quic/test_tools/quic_packet_creator_peer.cc index 0b9a1014..82ae990 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.cc +++ b/net/quic/test_tools/quic_packet_creator_peer.cc
@@ -60,5 +60,18 @@ creator->FillPacketHeader(fec_group, fec_flag, header); } +// static +size_t QuicPacketCreatorPeer::CreateStreamFrame(QuicPacketCreator* creator, + QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + bool fin, + QuicFrame* frame, + UniqueStreamBuffer* buffer) { + return creator->CreateStreamFrame(id, iov, iov_offset, offset, fin, frame, + buffer); +} + } // namespace test } // namespace net
diff --git a/net/quic/test_tools/quic_packet_creator_peer.h b/net/quic/test_tools/quic_packet_creator_peer.h index 305a20cd..72d29d9 100644 --- a/net/quic/test_tools/quic_packet_creator_peer.h +++ b/net/quic/test_tools/quic_packet_creator_peer.h
@@ -33,6 +33,14 @@ QuicFecGroupNumber fec_group, bool fec_flag, QuicPacketHeader* header); + static size_t CreateStreamFrame(QuicPacketCreator* creator, + QuicStreamId id, + QuicIOVector iov, + size_t iov_offset, + QuicStreamOffset offset, + bool fin, + QuicFrame* frame, + UniqueStreamBuffer* buffer); private: DISALLOW_COPY_AND_ASSIGN(QuicPacketCreatorPeer);
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc index adecf9c..3f417ec 100644 --- a/net/quic/test_tools/quic_test_packet_maker.cc +++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -175,7 +175,7 @@ QuicStreamId stream_id, bool should_include_version, bool fin, - QuicPriority priority, + SpdyPriority priority, const SpdyHeaderBlock& headers, size_t* spdy_headers_frame_length) { InitializeHeader(packet_number, should_include_version); @@ -208,7 +208,7 @@ QuicStreamId stream_id, bool should_include_version, bool fin, - QuicPriority priority, + SpdyPriority priority, const SpdyHeaderBlock& headers) { return MakeRequestHeadersPacket(packet_number, stream_id, should_include_version, fin, priority,
diff --git a/net/quic/test_tools/quic_test_packet_maker.h b/net/quic/test_tools/quic_test_packet_maker.h index adb2f3b..3c52350a 100644 --- a/net/quic/test_tools/quic_test_packet_maker.h +++ b/net/quic/test_tools/quic_test_packet_maker.h
@@ -61,7 +61,7 @@ QuicStreamId stream_id, bool should_include_version, bool fin, - QuicPriority priority, + SpdyPriority priority, const SpdyHeaderBlock& headers, size_t* spdy_headers_frame_length); @@ -72,7 +72,7 @@ QuicStreamId stream_id, bool should_include_version, bool fin, - QuicPriority priority, + SpdyPriority priority, const SpdyHeaderBlock& headers); // If |spdy_headers_frame_length| is non-null, it will be set to the size of
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index 8e1df7ad..6d8e35f 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h
@@ -440,8 +440,8 @@ QuicAckListenerInterface*)); MOCK_METHOD2(OnStreamHeaders, void(QuicStreamId stream_id, base::StringPiece headers_data)); - MOCK_METHOD2(OnStreamHeadersPriority, void(QuicStreamId stream_id, - QuicPriority priority)); + MOCK_METHOD2(OnStreamHeadersPriority, + void(QuicStreamId stream_id, SpdyPriority priority)); MOCK_METHOD3(OnStreamHeadersComplete, void(QuicStreamId stream_id, bool fin, size_t frame_len));
diff --git a/net/spdy/hpack/hpack_header_table.h b/net/spdy/hpack/hpack_header_table.h index e60a758..881bb7cf 100644 --- a/net/spdy/hpack/hpack_header_table.h +++ b/net/spdy/hpack/hpack_header_table.h
@@ -18,8 +18,6 @@ namespace net { -using base::StringPiece; - namespace test { class HpackHeaderTablePeer; } // namespace test @@ -62,10 +60,11 @@ const HpackEntry* GetByIndex(size_t index); // Returns the lowest-value entry having |name|, or NULL. - const HpackEntry* GetByName(StringPiece name); + const HpackEntry* GetByName(base::StringPiece name); // Returns the lowest-index matching entry, or NULL. - const HpackEntry* GetByNameAndValue(StringPiece name, StringPiece value); + const HpackEntry* GetByNameAndValue(base::StringPiece name, + base::StringPiece value); // Returns the index of an entry within this header table. size_t IndexOf(const HpackEntry* entry) const; @@ -81,8 +80,8 @@ // Determine the set of entries which would be evicted by the insertion // of |name| & |value| into the table, as per section 4.4. No eviction // actually occurs. The set is returned via range [begin_out, end_out). - void EvictionSet(StringPiece name, - StringPiece value, + void EvictionSet(base::StringPiece name, + base::StringPiece value, EntryTable::iterator* begin_out, EntryTable::iterator* end_out); @@ -90,13 +89,15 @@ // and |value| must not be owned by an entry which could be evicted. The // added HpackEntry is returned, or NULL is returned if all entries were // evicted and the empty table is of insufficent size for the representation. - const HpackEntry* TryAddEntry(StringPiece name, StringPiece value); + const HpackEntry* TryAddEntry(base::StringPiece name, + base::StringPiece value); void DebugLogTableState() const; private: // Returns number of evictions required to enter |name| & |value|. - size_t EvictionCountForEntry(StringPiece name, StringPiece value) const; + size_t EvictionCountForEntry(base::StringPiece name, + base::StringPiece value) const; // Returns number of evictions required to reclaim |reclaim_size| table size. size_t EvictionCountToReclaim(size_t reclaim_size) const;
diff --git a/net/spdy/hpack/hpack_static_table.cc b/net/spdy/hpack/hpack_static_table.cc index 8ee1d0b..b954c34 100644 --- a/net/spdy/hpack/hpack_static_table.cc +++ b/net/spdy/hpack/hpack_static_table.cc
@@ -21,10 +21,11 @@ int total_insertions = 0; for (const HpackStaticEntry* it = static_entry_table; it != static_entry_table + static_entry_count; ++it) { - static_entries_.push_back(HpackEntry(StringPiece(it->name, it->name_len), - StringPiece(it->value, it->value_len), - true, // is_static - total_insertions)); + static_entries_.push_back( + HpackEntry(base::StringPiece(it->name, it->name_len), + base::StringPiece(it->value, it->value_len), + true, // is_static + total_insertions)); CHECK(static_index_.insert(&static_entries_.back()).second); ++total_insertions;
diff --git a/net/spdy/spdy_alt_svc_wire_format.cc b/net/spdy/spdy_alt_svc_wire_format.cc index 0c1756b..f2f5ab7a 100644 --- a/net/spdy/spdy_alt_svc_wire_format.cc +++ b/net/spdy/spdy_alt_svc_wire_format.cc
@@ -12,6 +12,8 @@ namespace net { +using base::StringPiece; + namespace { template <class T>
diff --git a/net/spdy/spdy_alt_svc_wire_format.h b/net/spdy/spdy_alt_svc_wire_format.h index 317ae97..85dd0d3b 100644 --- a/net/spdy/spdy_alt_svc_wire_format.h +++ b/net/spdy/spdy_alt_svc_wire_format.h
@@ -16,8 +16,6 @@ #include "base/strings/string_piece.h" #include "net/base/net_export.h" -using base::StringPiece; - namespace net { namespace test { @@ -62,29 +60,29 @@ typedef std::vector<AlternativeService> AlternativeServiceVector; friend class test::SpdyAltSvcWireFormatPeer; - static bool ParseHeaderFieldValue(StringPiece value, + static bool ParseHeaderFieldValue(base::StringPiece value, AlternativeServiceVector* altsvc_vector); static std::string SerializeHeaderFieldValue( const AlternativeServiceVector& altsvc_vector); private: - static void SkipWhiteSpace(StringPiece::const_iterator* c, - StringPiece::const_iterator end); - static bool PercentDecode(StringPiece::const_iterator c, - StringPiece::const_iterator end, + static void SkipWhiteSpace(base::StringPiece::const_iterator* c, + base::StringPiece::const_iterator end); + static bool PercentDecode(base::StringPiece::const_iterator c, + base::StringPiece::const_iterator end, std::string* output); - static bool ParseAltAuthority(StringPiece::const_iterator c, - StringPiece::const_iterator end, + static bool ParseAltAuthority(base::StringPiece::const_iterator c, + base::StringPiece::const_iterator end, std::string* host, uint16* port); - static bool ParsePositiveInteger16(StringPiece::const_iterator c, - StringPiece::const_iterator end, + static bool ParsePositiveInteger16(base::StringPiece::const_iterator c, + base::StringPiece::const_iterator end, uint16* value); - static bool ParsePositiveInteger32(StringPiece::const_iterator c, - StringPiece::const_iterator end, + static bool ParsePositiveInteger32(base::StringPiece::const_iterator c, + base::StringPiece::const_iterator end, uint32* value); - static bool ParseProbability(StringPiece::const_iterator c, - StringPiece::const_iterator end, + static bool ParseProbability(base::StringPiece::const_iterator c, + base::StringPiece::const_iterator end, double* probability); };
diff --git a/net/spdy/spdy_alt_svc_wire_format_test.cc b/net/spdy/spdy_alt_svc_wire_format_test.cc index d69e4d6..f6db9f5 100644 --- a/net/spdy/spdy_alt_svc_wire_format_test.cc +++ b/net/spdy/spdy_alt_svc_wire_format_test.cc
@@ -9,6 +9,7 @@ #include "testing/platform_test.h" using ::testing::_; +using base::StringPiece; namespace net {
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index 29bb588..6b5f4d1b 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc
@@ -24,6 +24,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/platform_test.h" +using base::StringPiece; using std::string; using testing::_; @@ -611,8 +612,8 @@ }; // Retrieves serialized headers from a HEADERS or SYN_STREAM frame. -base::StringPiece GetSerializedHeaders(const SpdyFrame* frame, - const SpdyFramer& framer) { +StringPiece GetSerializedHeaders(const SpdyFrame* frame, + const SpdyFramer& framer) { SpdyFrameReader reader(frame->data(), frame->size()); if (framer.protocol_version() > SPDY3) { reader.Seek(3); // Seek past the frame length. @@ -931,7 +932,7 @@ SpdyHeaderBlock new_headers; framer.set_enable_compression(false); scoped_ptr<SpdyFrame> control_frame(frame.take()); - base::StringPiece serialized_headers = + StringPiece serialized_headers = GetSerializedHeaders(control_frame.get(), framer); // This should fail because duplicate headers are verboten by the spec. EXPECT_FALSE(framer.ParseHeaderBlockInBuffer(serialized_headers.data(), @@ -1276,7 +1277,7 @@ if (IsHttp2()) { EXPECT_EQ(3, visitor.headers_frame_count_); EXPECT_EQ(0, visitor.syn_frame_count_); - base::StringPiece reset_stream = "RESETSTREAM"; + StringPiece reset_stream = "RESETSTREAM"; EXPECT_EQ(reset_stream, visitor.fin_opaque_data_); } else { EXPECT_EQ(1, visitor.headers_frame_count_); @@ -1516,7 +1517,7 @@ // Now start decompressing scoped_ptr<SpdyFrame> decompressed; scoped_ptr<SpdyFrame> uncompressed; - base::StringPiece serialized_headers; + StringPiece serialized_headers; SpdyHeaderBlock decompressed_headers; // Decompress SYN_STREAM #1
diff --git a/net/spdy/spdy_header_block_test.cc b/net/spdy/spdy_header_block_test.cc index 2e449ba..c7bb283 100644 --- a/net/spdy/spdy_header_block_test.cc +++ b/net/spdy/spdy_header_block_test.cc
@@ -19,7 +19,8 @@ namespace net { -std::pair<StringPiece, StringPiece> Pair(StringPiece k, StringPiece v) { +std::pair<base::StringPiece, base::StringPiece> Pair(base::StringPiece k, + base::StringPiece v) { return make_pair(k, v); }
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 9208de2..d0cbd3f2b 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -831,7 +831,7 @@ void OnRstStream(SpdyStreamId stream_id, SpdyRstStreamStatus status) override; void OnGoAway(SpdyStreamId last_accepted_stream_id, SpdyGoAwayStatus status, - StringPiece debug_data) override; + base::StringPiece debug_data) override; void OnDataFrameHeader(SpdyStreamId stream_id, size_t length, bool fin) override;
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 27b8117..8225d0a 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -348,6 +348,7 @@ enable_compression(false), enable_ping(false), enable_user_alternate_protocol_ports(false), + enable_npn(true), protocol(protocol), session_max_recv_window_size( SpdySession::GetDefaultInitialWindowSize(protocol)), @@ -383,6 +384,7 @@ enable_compression(false), enable_ping(false), enable_user_alternate_protocol_ports(false), + enable_npn(true), protocol(protocol), session_max_recv_window_size( SpdySession::GetDefaultInitialWindowSize(protocol)), @@ -441,6 +443,7 @@ params.enable_spdy_ping_based_connection_checking = session_deps->enable_ping; params.enable_user_alternate_protocol_ports = session_deps->enable_user_alternate_protocol_ports; + params.enable_npn = session_deps->enable_npn; params.spdy_default_protocol = session_deps->protocol; params.spdy_session_max_recv_window_size = session_deps->session_max_recv_window_size;
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index 33c8b33..5316e31 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -197,6 +197,7 @@ bool enable_compression; bool enable_ping; bool enable_user_alternate_protocol_ports; + bool enable_npn; NextProto protocol; size_t session_max_recv_window_size; size_t stream_max_recv_window_size;
diff --git a/net/spdy/spdy_test_utils.h b/net/spdy/spdy_test_utils.h index a9ff5f3..fee91f68 100644 --- a/net/spdy/spdy_test_utils.h +++ b/net/spdy/spdy_test_utils.h
@@ -17,9 +17,9 @@ class HashValue; class TransportSecurityState; -inline bool operator==(StringPiece x, +inline bool operator==(base::StringPiece x, const SpdyHeaderBlock::StringPieceProxy& y) { - return x == y.operator StringPiece(); + return x == y.operator base::StringPiece(); } namespace test {
diff --git a/net/spdy/write_blocked_list.h b/net/spdy/write_blocked_list.h index 32ed19c..7622dc2 100644 --- a/net/spdy/write_blocked_list.h +++ b/net/spdy/write_blocked_list.h
@@ -81,29 +81,20 @@ return false; } + // Add this stream to the back of the write blocked list for this priority + // level. If the stream is already on that write blocked list this is a + // no-op. If the stream is on a write blocked list for a different priority + // it will be removed from that list. void PushBack(IdType stream_id, SpdyPriority priority) { - priority = ClampPriority(priority); - DVLOG(2) << "Adding stream " << stream_id << " at priority " - << static_cast<int>(priority); - bool should_insert_stream = true; - typename StreamToPriorityMap::iterator iter = - stream_to_priority_.find(stream_id); - if (iter != stream_to_priority_.end()) { - DVLOG(1) << "Stream " << stream_id << " already in write blocked list."; - if (iter->second == priority) { - // The stream is already in the write blocked list for the priority. - should_insert_stream = false; - } else { - // The stream is in a write blocked list for a different priority. - bool removed = - RemoveStreamFromWriteBlockedList(stream_id, iter->second); - DCHECK(removed); - } - } - if (should_insert_stream) { - stream_to_priority_[stream_id] = priority; - write_blocked_lists_[priority].push_back(stream_id); - } + AddStream(stream_id, priority, true); + } + + // Add this stream to the front of the write blocked list for this priority + // level. If the stream is already on that write blocked list this is a + // no-op. If the stream is on a write blocked list for a different priority + // it will be removed from that list. + void PushFront(IdType stream_id, SpdyPriority priority) { + AddStream(stream_id, priority, false); } bool RemoveStreamFromWriteBlockedList(IdType stream_id, @@ -153,11 +144,48 @@ return num_blocked_streams; } + size_t NumBlockedStreams(SpdyPriority priority) const { + priority = ClampPriority(priority); + return write_blocked_lists_[priority].size(); + } + private: friend class net::test::WriteBlockedListPeer; typedef base::hash_map<IdType, SpdyPriority> StreamToPriorityMap; + void AddStream(IdType stream_id, SpdyPriority priority, bool push_back) { + priority = ClampPriority(priority); + DVLOG(2) << "Adding stream " << stream_id << " at priority " + << static_cast<int>(priority); + bool should_insert_stream = true; + typename StreamToPriorityMap::iterator iter = + stream_to_priority_.find(stream_id); + // Ensure the stream is not in the write blocked list multiple times. + if (iter != stream_to_priority_.end()) { + DVLOG(1) << "Stream " << stream_id << " already in write blocked list."; + if (iter->second == priority) { + // The stream is already in the write blocked list for the priority. + // It will not be inserted again but will retain its place in the list. + should_insert_stream = false; + } else { + // The stream is in a write blocked list for a different priority. + // Remove it from that list and allow it to be added to the list for + // this priority. + bool removed = + RemoveStreamFromWriteBlockedList(stream_id, iter->second); + DCHECK(removed); + } + } + if (should_insert_stream) { + stream_to_priority_[stream_id] = priority; + if (push_back) { + write_blocked_lists_[priority].push_back(stream_id); + } else { + write_blocked_lists_[priority].push_front(stream_id); + } + } + } BlockedList write_blocked_lists_[kLowestPriority + 1]; StreamToPriorityMap stream_to_priority_; };
diff --git a/net/spdy/write_blocked_list_test.cc b/net/spdy/write_blocked_list_test.cc index 20a1b7e4..933dc71 100644 --- a/net/spdy/write_blocked_list_test.cc +++ b/net/spdy/write_blocked_list_test.cc
@@ -78,6 +78,34 @@ EXPECT_EQ(3, list.PopFront(4)); } +TEST_F(WriteBlockedListTest, PushFront) { + list.PushFront(1, 4); + EXPECT_EQ(1u, list.NumBlockedStreams()); + list.PushFront(2, 4); + list.PushFront(1, 4); + list.PushFront(3, 4); + EXPECT_EQ(3u, list.NumBlockedStreams()); + + EXPECT_EQ(3, list.PopFront(4)); + EXPECT_EQ(2, list.PopFront(4)); + EXPECT_EQ(1u, list.NumBlockedStreams()); + EXPECT_EQ(1, list.PopFront(4)); +} + +TEST_F(WriteBlockedListTest, PushFrontAndBack) { + list.PushFront(1, 4); + list.PushBack(5, 4); + list.PushFront(2, 4); + list.PushBack(3, 4); + list.PushFront(4, 4); + + EXPECT_EQ(4, list.PopFront(4)); + EXPECT_EQ(2, list.PopFront(4)); + EXPECT_EQ(1, list.PopFront(4)); + EXPECT_EQ(5, list.PopFront(4)); + EXPECT_EQ(3, list.PopFront(4)); +} + TEST_F(WriteBlockedListTest, UpdateStreamPriorityInWriteBlockedList) { list.PushBack(1, 1); list.PushBack(2, 2);
diff --git a/net/ssl/threaded_ssl_private_key.h b/net/ssl/threaded_ssl_private_key.h index ad77e36..6fe9987 100644 --- a/net/ssl/threaded_ssl_private_key.h +++ b/net/ssl/threaded_ssl_private_key.h
@@ -38,7 +38,7 @@ virtual std::vector<SSLPrivateKey::Hash> GetDigestPreferences() = 0; virtual size_t GetMaxSignatureLengthInBytes() = 0; - // Signs |input| as a digest of type |hash|. On sucess it returns OK and + // Signs |input| as a digest of type |hash|. On success it returns OK and // sets |signature| to the resulting signature. Otherwise it returns a net // error code. It will only be called on the task runner passed to the // owning ThreadedSSLPrivateKey.
diff --git a/net/test/url_request/url_request_failed_job.cc b/net/test/url_request/url_request_failed_job.cc index e4ac6a6..d7c479b 100644 --- a/net/test/url_request/url_request_failed_job.cc +++ b/net/test/url_request/url_request_failed_job.cc
@@ -97,40 +97,20 @@ } void URLRequestFailedJob::Start() { - if (phase_ == START) { - if (net_error_ != ERR_IO_PENDING) { - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, net_error_)); - return; - } - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - return; - } - response_info_.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); - NotifyHeadersComplete(); -} - -bool URLRequestFailedJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { - CHECK(phase_ == READ_SYNC || phase_ == READ_ASYNC); - if (net_error_ != ERR_IO_PENDING && phase_ == READ_SYNC) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net_error_)); - return false; - } - - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - - if (net_error_ == ERR_IO_PENDING) - return false; - - DCHECK_EQ(READ_ASYNC, phase_); - DCHECK_NE(ERR_IO_PENDING, net_error_); - base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, - base::Bind(&URLRequestFailedJob::NotifyDone, weak_factory_.GetWeakPtr(), - URLRequestStatus(URLRequestStatus::FAILED, net_error_))); - return false; + base::Bind(&URLRequestFailedJob::StartAsync, weak_factory_.GetWeakPtr())); +} + +int URLRequestFailedJob::ReadRawData(IOBuffer* buf, int buf_size) { + CHECK(phase_ == READ_SYNC || phase_ == READ_ASYNC); + if (net_error_ == ERR_IO_PENDING || phase_ == READ_SYNC) + return net_error_; + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&URLRequestFailedJob::ReadRawDataComplete, + weak_factory_.GetWeakPtr(), net_error_)); + return ERR_IO_PENDING; } int URLRequestFailedJob::GetResponseCode() const { @@ -195,4 +175,17 @@ URLRequestFailedJob::~URLRequestFailedJob() { } +void URLRequestFailedJob::StartAsync() { + if (phase_ == START) { + if (net_error_ != ERR_IO_PENDING) { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, net_error_)); + return; + } + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + return; + } + response_info_.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); + NotifyHeadersComplete(); +} + } // namespace net
diff --git a/net/test/url_request/url_request_failed_job.h b/net/test/url_request/url_request_failed_job.h index 0413111..45b1911 100644 --- a/net/test/url_request/url_request_failed_job.h +++ b/net/test/url_request/url_request_failed_job.h
@@ -39,7 +39,7 @@ // URLRequestJob implementation: void Start() override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; int GetResponseCode() const override; void GetResponseInfo(HttpResponseInfo* info) override; @@ -71,6 +71,7 @@ protected: ~URLRequestFailedJob() override; + void StartAsync(); private: HttpResponseInfo response_info_;
diff --git a/net/test/url_request/url_request_mock_data_job.cc b/net/test/url_request/url_request_mock_data_job.cc index fbc97dc7..3b3f9d3 100644 --- a/net/test/url_request/url_request_mock_data_job.cc +++ b/net/test/url_request/url_request_mock_data_job.cc
@@ -117,15 +117,12 @@ URLRequestMockDataJob::~URLRequestMockDataJob() { } -bool URLRequestMockDataJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { - DCHECK(bytes_read); - *bytes_read = static_cast<int>( - std::min(static_cast<size_t>(buf_size), data_.length() - data_offset_)); - memcpy(buf->data(), data_.c_str() + data_offset_, *bytes_read); - data_offset_ += *bytes_read; - return true; +int URLRequestMockDataJob::ReadRawData(IOBuffer* buf, int buf_size) { + int bytes_read = + std::min(static_cast<size_t>(buf_size), data_.length() - data_offset_); + memcpy(buf->data(), data_.c_str() + data_offset_, bytes_read); + data_offset_ += bytes_read; + return bytes_read; } int URLRequestMockDataJob::GetResponseCode() const {
diff --git a/net/test/url_request/url_request_mock_data_job.h b/net/test/url_request/url_request_mock_data_job.h index ea35a6ee..91189ba 100644 --- a/net/test/url_request/url_request_mock_data_job.h +++ b/net/test/url_request/url_request_mock_data_job.h
@@ -27,7 +27,7 @@ bool request_client_certificate); void Start() override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; int GetResponseCode() const override; void GetResponseInfo(HttpResponseInfo* info) override; void ContinueWithCertificate(X509Certificate* client_cert,
diff --git a/net/test/url_request/url_request_slow_download_job.cc b/net/test/url_request/url_request_slow_download_job.cc index f344feb..52fd71c 100644 --- a/net/test/url_request/url_request_slow_download_job.cc +++ b/net/test/url_request/url_request_slow_download_job.cc
@@ -179,39 +179,34 @@ return REQUEST_COMPLETE; } -bool URLRequestSlowDownloadJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { +int URLRequestSlowDownloadJob::ReadRawData(IOBuffer* buf, int buf_size) { if (base::LowerCaseEqualsASCII(kFinishDownloadUrl, request_->url().spec().c_str()) || base::LowerCaseEqualsASCII(kErrorDownloadUrl, request_->url().spec().c_str())) { VLOG(10) << __FUNCTION__ << " called w/ kFinish/ErrorDownloadUrl."; - *bytes_read = 0; - return true; + return 0; } VLOG(10) << __FUNCTION__ << " called at position " << bytes_already_sent_ << " in the stream."; - ReadStatus status = FillBufferHelper(buf, buf_size, bytes_read); + int bytes_read = 0; + ReadStatus status = FillBufferHelper(buf, buf_size, &bytes_read); switch (status) { case BUFFER_FILLED: - return true; + case REQUEST_COMPLETE: + return bytes_read; case REQUEST_BLOCKED: buffer_ = buf; buffer_size_ = buf_size; - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus, weak_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(100)); - return false; - case REQUEST_COMPLETE: - *bytes_read = 0; - return true; + return ERR_IO_PENDING; } NOTREACHED(); - return true; + return OK; } void URLRequestSlowDownloadJob::CheckDoneStatus() { @@ -223,12 +218,10 @@ FillBufferHelper(buffer_.get(), buffer_size_, &bytes_written); DCHECK_EQ(BUFFER_FILLED, status); buffer_ = NULL; // Release the reference. - SetStatus(URLRequestStatus()); - NotifyReadComplete(bytes_written); + ReadRawDataComplete(bytes_written); } else if (should_error_download_) { VLOG(10) << __FUNCTION__ << " called w/ should_finish_ownload_ set."; - NotifyDone( - URLRequestStatus(URLRequestStatus::FAILED, ERR_CONNECTION_RESET)); + ReadRawDataComplete(ERR_CONNECTION_RESET); } else { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus,
diff --git a/net/test/url_request/url_request_slow_download_job.h b/net/test/url_request/url_request_slow_download_job.h index 115a6ac..fcd7f661b 100644 --- a/net/test/url_request/url_request_slow_download_job.h +++ b/net/test/url_request/url_request_slow_download_job.h
@@ -37,7 +37,7 @@ void Start() override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(HttpResponseInfo* info) override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; // Returns the current number of URLRequestSlowDownloadJobs that have // not yet completed.
diff --git a/net/tools/flip_server/spdy_interface.h b/net/tools/flip_server/spdy_interface.h index e9918a8..b959419 100644 --- a/net/tools/flip_server/spdy_interface.h +++ b/net/tools/flip_server/spdy_interface.h
@@ -140,7 +140,7 @@ // Called when a GOAWAY frame has been parsed. void OnGoAway(SpdyStreamId last_accepted_stream_id, SpdyGoAwayStatus status, - StringPiece debug_data) override {} + base::StringPiece debug_data) override {} // Called when a WINDOW_UPDATE frame has been parsed. void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {}
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 3003929..3cd4ff0f 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -1379,7 +1379,6 @@ int max_streams = 100; AddToCache("/large_response", 200, large_body); - ; client_->client()->WaitForCryptoHandshakeConfirmed(); SetPacketLossPercentage(10);
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc index 67718c1a..ec0770a 100644 --- a/net/tools/quic/quic_client_session_test.cc +++ b/net/tools/quic/quic_client_session_test.cc
@@ -95,17 +95,10 @@ // Close the stream, but without having received a FIN or a RST_STREAM // and check that a new one can not be created. session_->CloseStream(stream->id()); - if (FLAGS_quic_count_unfinished_as_open_streams) { - EXPECT_EQ(1u, session_->GetNumOpenStreams()); - } else { - EXPECT_EQ(0u, session_->GetNumOpenStreams()); - } + EXPECT_EQ(1u, session_->GetNumOpenStreams()); + stream = session_->CreateOutgoingDynamicStream(); - if (FLAGS_quic_count_unfinished_as_open_streams) { - EXPECT_FALSE(stream); - } else { - EXPECT_TRUE(stream); - } + EXPECT_FALSE(stream); } TEST_P(ToolsQuicClientSessionTest, MaxNumStreamsWithRst) {
diff --git a/net/tools/quic/quic_in_memory_cache.h b/net/tools/quic/quic_in_memory_cache.h index 5703b9f5..5aee73a 100644 --- a/net/tools/quic/quic_in_memory_cache.h +++ b/net/tools/quic/quic_in_memory_cache.h
@@ -46,7 +46,7 @@ SpecialResponseType response_type() const { return response_type_; } const SpdyHeaderBlock& headers() const { return headers_; } - const StringPiece body() const { return StringPiece(body_); } + const base::StringPiece body() const { return base::StringPiece(body_); } void set_response_type(SpecialResponseType response_type) { response_type_ = response_type;
diff --git a/net/tools/quic/quic_packet_reader.cc b/net/tools/quic/quic_packet_reader.cc index 1f368a6..90f0587 100644 --- a/net/tools/quic/quic_packet_reader.cc +++ b/net/tools/quic/quic_packet_reader.cc
@@ -104,12 +104,8 @@ packets_dropped); } - if (FLAGS_quic_read_packets_full_recvmmsg) { - // We may not have read all of the packets available on the socket. - return packets_read == kNumPacketsPerReadMmsgCall; - } else { - return true; - } + // We may not have read all of the packets available on the socket. + return packets_read == kNumPacketsPerReadMmsgCall; #else LOG(FATAL) << "Unsupported"; return false;
diff --git a/net/tools/quic/quic_server_session_test.cc b/net/tools/quic/quic_server_session_test.cc index 173ea53..b447ff8 100644 --- a/net/tools/quic/quic_server_session_test.cc +++ b/net/tools/quic/quic_server_session_test.cc
@@ -367,8 +367,8 @@ &bandwidth_recorder, max_bandwidth_estimate_kbytes_per_second, max_bandwidth_estimate_timestamp); // Queue up some pending data. - session_->MarkConnectionLevelWriteBlocked( - kCryptoStreamId, QuicWriteBlockedList::kHighestPriority); + session_->MarkConnectionLevelWriteBlocked(kCryptoStreamId, + net::kHighestPriority); EXPECT_TRUE(session_->HasDataToWrite()); // There will be no update sent yet - not enough time has passed.
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index b6f1768..2243f89 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -587,7 +587,6 @@ } const IPEndPoint& QuicTestClient::address() const { - LOG(DFATAL) << "Not implemented"; return client_->server_address(); }
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h index 4d54f18..f122e8b 100644 --- a/net/tools/quic/test_tools/quic_test_client.h +++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -170,7 +170,7 @@ void set_auto_reconnect(bool reconnect) { auto_reconnect_ = reconnect; } - void set_priority(QuicPriority priority) { priority_ = priority; } + void set_priority(SpdyPriority priority) { priority_ = priority; } // Sets client's FEC policy. This policy applies to the data stream(s), and // also to the headers and crypto streams. @@ -226,7 +226,7 @@ bool response_complete_; bool response_headers_complete_; mutable BalsaHeaders headers_; - QuicPriority priority_; + SpdyPriority priority_; std::string response_; uint64 bytes_read_; uint64 bytes_written_;
diff --git a/net/tools/quic/test_tools/quic_test_server.cc b/net/tools/quic/test_tools/quic_test_server.cc index baf33af..95530f2 100644 --- a/net/tools/quic/test_tools/quic_test_server.cc +++ b/net/tools/quic/test_tools/quic_test_server.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/run_loop.h" +#include "base/synchronization/lock.h" #include "base/thread_task_runner_handle.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" @@ -76,6 +77,7 @@ QuicServerSession* CreateQuicSession(QuicConnectionId id, const IPEndPoint& client) override { + base::AutoLock lock(factory_lock_); if (session_factory_ == nullptr && stream_factory_ == nullptr && crypto_stream_factory_ == nullptr) { return QuicDispatcher::CreateQuicSession(id, client); @@ -97,30 +99,30 @@ return session; } - void set_session_factory(QuicTestServer::SessionFactory* factory) { + void SetSessionFactory(QuicTestServer::SessionFactory* factory) { + base::AutoLock lock(factory_lock_); DCHECK(session_factory_ == nullptr); DCHECK(stream_factory_ == nullptr); DCHECK(crypto_stream_factory_ == nullptr); session_factory_ = factory; } - void set_stream_factory(QuicTestServer::StreamFactory* factory) { + void SetStreamFactory(QuicTestServer::StreamFactory* factory) { + base::AutoLock lock(factory_lock_); DCHECK(session_factory_ == nullptr); DCHECK(stream_factory_ == nullptr); stream_factory_ = factory; } - void set_crypto_stream_factory(QuicTestServer::CryptoStreamFactory* factory) { + void SetCryptoStreamFactory(QuicTestServer::CryptoStreamFactory* factory) { + base::AutoLock lock(factory_lock_); DCHECK(session_factory_ == nullptr); DCHECK(crypto_stream_factory_ == nullptr); crypto_stream_factory_ = factory; } - QuicTestServer::SessionFactory* session_factory() { return session_factory_; } - - QuicTestServer::StreamFactory* stream_factory() { return stream_factory_; } - private: + base::Lock factory_lock_; QuicTestServer::SessionFactory* session_factory_; // Not owned. QuicTestServer::StreamFactory* stream_factory_; // Not owned. QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned. @@ -143,16 +145,16 @@ void QuicTestServer::SetSessionFactory(SessionFactory* factory) { DCHECK(dispatcher()); - static_cast<QuicTestDispatcher*>(dispatcher())->set_session_factory(factory); + static_cast<QuicTestDispatcher*>(dispatcher())->SetSessionFactory(factory); } void QuicTestServer::SetSpdyStreamFactory(StreamFactory* factory) { - static_cast<QuicTestDispatcher*>(dispatcher())->set_stream_factory(factory); + static_cast<QuicTestDispatcher*>(dispatcher())->SetStreamFactory(factory); } void QuicTestServer::SetCryptoStreamFactory(CryptoStreamFactory* factory) { static_cast<QuicTestDispatcher*>(dispatcher()) - ->set_crypto_stream_factory(factory); + ->SetCryptoStreamFactory(factory); } /////////////////////////// TEST SESSIONS ///////////////////////////////
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index b64f511..c943f4c 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -8,11 +8,14 @@ #include "base/bind_helpers.h" #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/debug/alias.h" +#include "base/debug/dump_without_crashing.h" #include "base/debug/stack_trace.h" #include "base/lazy_instance.h" #include "base/memory/singleton.h" #include "base/message_loop/message_loop.h" #include "base/profiler/scoped_tracker.h" +#include "base/rand_util.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" @@ -682,6 +685,23 @@ void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) { DCHECK(error < 0); + // ~500,000 ERR_ABORTED < 100ms in Canary channel a day. Sample .01% to get + // ~50 reports a day. + // TODO(csharrison) Remove this code when crbug.com/557430 is resolved. + int64 request_time = + (base::TimeTicks::Now() - creation_time_).InMilliseconds(); + if (error == ERR_ABORTED && request_time <= 100 && + load_flags_ & LOAD_MAIN_FRAME && base::RandDouble() < .0001) { + static int dump_times = 0; + if (dump_times < 5) { + char url_copy[256] = {0}; + strncpy(url_copy, url().spec().c_str(), sizeof(url_copy)); + base::debug::Alias(&url_copy); + base::debug::Alias(&request_time); + base::debug::DumpWithoutCrashing(); + dump_times++; + } + } // If cancelled while calling a delegate, clear delegate info. if (calling_delegate_) { LogUnblocked();
diff --git a/net/url_request/url_request_file_dir_job.cc b/net/url_request/url_request_file_dir_job.cc index 114672ea..1dafbf2 100644 --- a/net/url_request/url_request_file_dir_job.cc +++ b/net/url_request/url_request_file_dir_job.cc
@@ -13,7 +13,6 @@ #include "base/thread_task_runner_handle.h" #include "base/time/time.h" #include "net/base/io_buffer.h" -#include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/url_request/url_request_status.h" #include "url/gurl.h" @@ -66,24 +65,19 @@ weak_factory_.InvalidateWeakPtrs(); } -bool URLRequestFileDirJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { - DCHECK(bytes_read); - *bytes_read = 0; - +int URLRequestFileDirJob::ReadRawData(IOBuffer* buf, int buf_size) { if (is_done()) - return true; + return 0; - if (FillReadBuffer(buf->data(), buf_size, bytes_read)) - return true; + int bytes_read = 0; + if (FillReadBuffer(buf->data(), buf_size, &bytes_read)) + return bytes_read; // We are waiting for more data read_pending_ = true; read_buffer_ = buf; read_buffer_length_ = buf_size; - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - return false; + return ERR_IO_PENDING; } bool URLRequestFileDirJob::GetMimeType(std::string* mime_type) const { @@ -132,40 +126,45 @@ data.info.GetLastModifiedTime())); // TODO(darin): coalesce more? - CompleteRead(); + CompleteRead(OK); } void URLRequestFileDirJob::OnListDone(int error) { DCHECK(!canceled_); - if (error != OK) { - read_pending_ = false; - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, error)); - } else { + DCHECK_LE(error, OK); + if (error == OK) list_complete_ = true; - CompleteRead(); - } + CompleteRead(static_cast<Error>(error)); } URLRequestFileDirJob::~URLRequestFileDirJob() {} -void URLRequestFileDirJob::CompleteRead() { - if (read_pending_) { - int bytes_read; +void URLRequestFileDirJob::CompleteRead(Error status) { + DCHECK_LE(status, OK); + DCHECK_NE(status, ERR_IO_PENDING); + + // Do nothing if there is no read pending. + if (!read_pending_) + return; + + int result = status; + if (status == OK) { + int filled_bytes = 0; if (FillReadBuffer(read_buffer_->data(), read_buffer_length_, - &bytes_read)) { + &filled_bytes)) { + result = filled_bytes; // We completed the read, so reset the read buffer. - read_pending_ = false; read_buffer_ = NULL; read_buffer_length_ = 0; - - SetStatus(URLRequestStatus()); - NotifyReadComplete(bytes_read); } else { NOTREACHED(); // TODO: Better error code. - NotifyDone(URLRequestStatus::FromError(ERR_FAILED)); + result = ERR_FAILED; } } + + read_pending_ = false; + ReadRawDataComplete(result); } bool URLRequestFileDirJob::FillReadBuffer(char* buf, int buf_size,
diff --git a/net/url_request/url_request_file_dir_job.h b/net/url_request/url_request_file_dir_job.h index 067db81e..f7a7b45 100644 --- a/net/url_request/url_request_file_dir_job.h +++ b/net/url_request/url_request_file_dir_job.h
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "net/base/directory_lister.h" +#include "net/base/net_errors.h" #include "net/url_request/url_request_job.h" namespace net { @@ -29,7 +30,7 @@ // Overridden from URLRequestJob: void Start() override; void Kill() override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; bool GetMimeType(std::string* mime_type) const override; bool GetCharset(std::string* charset) override; @@ -45,7 +46,7 @@ // When we have data and a read has been pending, this function // will fill the response buffer and notify the request // appropriately. - void CompleteRead(); + void CompleteRead(Error error); // Fills a buffer with the output. bool FillReadBuffer(char* buf, int buf_size, int* bytes_read); @@ -67,6 +68,7 @@ bool read_pending_; scoped_refptr<IOBuffer> read_buffer_; int read_buffer_length_; + base::WeakPtrFactory<URLRequestFileDirJob> weak_factory_; DISALLOW_COPY_AND_ASSIGN(URLRequestFileDirJob);
diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc index 06e1ba6b..2c5cf6a 100644 --- a/net/url_request/url_request_file_job.cc +++ b/net/url_request/url_request_file_job.cc
@@ -33,7 +33,6 @@ #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/mime_util.h" -#include "net/base/net_errors.h" #include "net/filter/filter.h" #include "net/http/http_util.h" #include "net/url_request/url_request_error_job.h" @@ -63,6 +62,7 @@ stream_(new FileStream(file_task_runner)), file_task_runner_(file_task_runner), remaining_bytes_(0), + range_parse_result_(OK), weak_ptr_factory_(this) {} void URLRequestFileJob::Start() { @@ -83,22 +83,17 @@ URLRequestJob::Kill(); } -bool URLRequestFileJob::ReadRawData(IOBuffer* dest, - int dest_size, - int* bytes_read) { +int URLRequestFileJob::ReadRawData(IOBuffer* dest, int dest_size) { DCHECK_NE(dest_size, 0); - DCHECK(bytes_read); DCHECK_GE(remaining_bytes_, 0); if (remaining_bytes_ < dest_size) - dest_size = static_cast<int>(remaining_bytes_); + dest_size = remaining_bytes_; // If we should copy zero bytes because |remaining_bytes_| is zero, short // circuit here. - if (!dest_size) { - *bytes_read = 0; - return true; - } + if (!dest_size) + return 0; int rv = stream_->Read(dest, dest_size, @@ -106,20 +101,11 @@ weak_ptr_factory_.GetWeakPtr(), make_scoped_refptr(dest))); if (rv >= 0) { - // Data is immediately available. - *bytes_read = rv; remaining_bytes_ -= rv; DCHECK_GE(remaining_bytes_, 0); - return true; } - // Otherwise, a read error occured. We may just need to wait... - if (rv == ERR_IO_PENDING) { - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - } else { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); - } - return false; + return rv; } bool URLRequestFileJob::IsRedirectResponse(GURL* location, @@ -179,7 +165,10 @@ const HttpRequestHeaders& headers) { std::string range_header; if (headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) { - // We only care about "Range" header here. + // This job only cares about the Range header. This method stashes the value + // for later use in DidOpen(), which is responsible for some of the range + // validation as well. NotifyStartError is not legal to call here since + // the job has not started. std::vector<HttpByteRange> ranges; if (HttpUtil::ParseRangeHeader(range_header, &ranges)) { if (ranges.size() == 1) { @@ -189,8 +178,7 @@ // because we need to do multipart encoding here. // TODO(hclam): decide whether we want to support multiple range // requests. - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; } } } @@ -251,13 +239,19 @@ void URLRequestFileJob::DidOpen(int result) { if (result != OK) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); + return; + } + + if (range_parse_result_ != net::OK) { + NotifyStartError( + URLRequestStatus(URLRequestStatus::FAILED, range_parse_result_)); return; } if (!byte_range_.ComputeBounds(meta_info_.file_size)) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -285,8 +279,8 @@ void URLRequestFileJob::DidSeek(int64 result) { OnSeekComplete(result); if (result != byte_range_.first_byte_position()) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -295,8 +289,7 @@ } void URLRequestFileJob::DidRead(scoped_refptr<IOBuffer> buf, int result) { - if (result > 0) { - SetStatus(URLRequestStatus()); // Clear the IO_PENDING status + if (result >= 0) { remaining_bytes_ -= result; DCHECK_GE(remaining_bytes_, 0); } @@ -304,13 +297,7 @@ OnReadComplete(buf.get(), result); buf = NULL; - if (result == 0) { - NotifyDone(URLRequestStatus()); - } else if (result < 0) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); - } - - NotifyReadComplete(result); + ReadRawDataComplete(result); } } // namespace net
diff --git a/net/url_request/url_request_file_job.h b/net/url_request/url_request_file_job.h index 0436dac5..97c6c21 100644 --- a/net/url_request/url_request_file_job.h +++ b/net/url_request/url_request_file_job.h
@@ -11,6 +11,7 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request.h" @@ -38,7 +39,7 @@ // URLRequestJob: void Start() override; void Kill() override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; Filter* SetupFilter() const override; bool GetMimeType(std::string* mime_type) const override; @@ -97,9 +98,12 @@ FileMetaInfo meta_info_; const scoped_refptr<base::TaskRunner> file_task_runner_; + std::vector<HttpByteRange> byte_ranges_; HttpByteRange byte_range_; int64 remaining_bytes_; + Error range_parse_result_; + base::WeakPtrFactory<URLRequestFileJob> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(URLRequestFileJob);
diff --git a/net/url_request/url_request_ftp_job.cc b/net/url_request/url_request_ftp_job.cc index 3a088bd..e422d03 100644 --- a/net/url_request/url_request_ftp_job.cc +++ b/net/url_request/url_request_ftp_job.cc
@@ -239,7 +239,7 @@ HandleAuthNeededResponse(); return; } else { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); } } @@ -251,15 +251,7 @@ void URLRequestFtpJob::OnReadCompleted(int result) { read_in_progress_ = false; - if (result == 0) { - NotifyDone(URLRequestStatus()); - } else if (result < 0) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); - } else { - // Clear the IO_PENDING status - SetStatus(URLRequestStatus()); - } - NotifyReadComplete(result); + ReadRawDataComplete(result); } void URLRequestFtpJob::RestartTransactionWithAuth() { @@ -352,14 +344,12 @@ return UploadProgress(); } -bool URLRequestFtpJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { +int URLRequestFtpJob::ReadRawData(IOBuffer* buf, int buf_size) { DCHECK_NE(buf_size, 0); - DCHECK(bytes_read); DCHECK(!read_in_progress_); int rv; + if (proxy_info_.is_direct()) { rv = ftp_transaction_->Read(buf, buf_size, base::Bind(&URLRequestFtpJob::OnReadCompleted, @@ -370,18 +360,9 @@ base::Unretained(this))); } - if (rv >= 0) { - *bytes_read = rv; - return true; - } - - if (rv == ERR_IO_PENDING) { + if (rv == ERR_IO_PENDING) read_in_progress_ = true; - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - } else { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); - } - return false; + return rv; } void URLRequestFtpJob::HandleAuthNeededResponse() {
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h index 74caf726..6315d8f 100644 --- a/net/url_request/url_request_ftp_job.h +++ b/net/url_request/url_request_ftp_job.h
@@ -71,7 +71,7 @@ // TODO(ibrar): Yet to give another look at this function. UploadProgress GetUploadProgress() const override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; void HandleAuthNeededResponse();
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index a452ec2..0254a5a 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -414,11 +414,6 @@ URLRequestJob::NotifyHeadersComplete(); } -void URLRequestHttpJob::NotifyDone(const URLRequestStatus& status) { - DoneWithRequest(FINISHED); - URLRequestJob::NotifyDone(status); -} - void URLRequestHttpJob::DestroyTransaction() { DCHECK(transaction_.get()); @@ -998,19 +993,16 @@ void URLRequestHttpJob::OnReadCompleted(int result) { read_in_progress_ = false; + DCHECK_NE(ERR_IO_PENDING, result); + if (ShouldFixMismatchedContentLength(result)) result = OK; - if (result == OK) { - NotifyDone(URLRequestStatus()); - } else if (result < 0) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); - } else { - // Clear the IO_PENDING status - SetStatus(URLRequestStatus()); - } + // EOF or error, done with this job. + if (result <= 0) + DoneWithRequest(FINISHED); - NotifyReadComplete(result); + ReadRawDataComplete(result); } void URLRequestHttpJob::RestartTransactionWithAuth( @@ -1336,11 +1328,8 @@ return false; } -bool URLRequestHttpJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { +int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) { DCHECK_NE(buf_size, 0); - DCHECK(bytes_read); DCHECK(!read_in_progress_); int rv = transaction_->Read( @@ -1348,23 +1337,15 @@ base::Bind(&URLRequestHttpJob::OnReadCompleted, base::Unretained(this))); if (ShouldFixMismatchedContentLength(rv)) - rv = 0; + rv = OK; - if (rv >= 0) { - *bytes_read = rv; - if (!rv) - DoneWithRequest(FINISHED); - return true; - } + if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING)) + DoneWithRequest(FINISHED); - if (rv == ERR_IO_PENDING) { + if (rv == ERR_IO_PENDING) read_in_progress_ = true; - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - } else { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); - } - return false; + return rv; } void URLRequestHttpJob::StopCaching() {
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 3d164c3..62162b5 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -79,9 +79,6 @@ // Shadows URLRequestJob's version of this method so we can grab cookies. void NotifyHeadersComplete(); - // Shadows URLRequestJob's method so we can record histograms. - void NotifyDone(const URLRequestStatus& status); - void DestroyTransaction(); void AddExtraHeaders(); @@ -133,7 +130,7 @@ SSLPrivateKey* client_private_key) override; void ContinueDespiteLastError() override; void ResumeNetworkStart() override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; void StopCaching() override; bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; int64 GetTotalReceivedBytes() const override;
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 39ccf31..1b5c8f2a 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -101,45 +101,46 @@ request_ = NULL; } -// This function calls ReadData to get stream data. If a filter exists, passes -// the data to the attached filter. Then returns the output from filter back to -// the caller. +// This function calls ReadRawData to get stream data. If a filter exists, it +// passes the data to the attached filter. It then returns the output from +// filter back to the caller. bool URLRequestJob::Read(IOBuffer* buf, int buf_size, int *bytes_read) { - bool rv = false; - DCHECK_LT(buf_size, 1000000); // Sanity check. DCHECK(buf); DCHECK(bytes_read); DCHECK(filtered_read_buffer_.get() == NULL); DCHECK_EQ(0, filtered_read_buffer_len_); + Error error = OK; *bytes_read = 0; // Skip Filter if not present. - if (!filter_.get()) { - rv = ReadRawDataHelper(buf, buf_size, bytes_read); + if (!filter_) { + error = ReadRawDataHelper(buf, buf_size, bytes_read); } else { // Save the caller's buffers while we do IO // in the filter's buffers. filtered_read_buffer_ = buf; filtered_read_buffer_len_ = buf_size; - if (ReadFilteredData(bytes_read)) { - rv = true; // We have data to return. + error = ReadFilteredData(bytes_read); - // It is fine to call DoneReading even if ReadFilteredData receives 0 - // bytes from the net, but we avoid making that call if we know for - // sure that's the case (ReadRawDataHelper path). - if (*bytes_read == 0) - DoneReading(); - } else { - rv = false; // Error, or a new IO is pending. - } + // Synchronous EOF from the filter. + if (error == OK && *bytes_read == 0) + DoneReading(); } - if (rv && *bytes_read == 0) - NotifyDone(URLRequestStatus()); - return rv; + if (error == OK) { + // If URLRequestJob read zero bytes, the job is at EOF. + if (*bytes_read == 0) + NotifyDone(URLRequestStatus()); + } else if (error == ERR_IO_PENDING) { + SetStatus(URLRequestStatus::FromError(ERR_IO_PENDING)); + } else { + NotifyDone(URLRequestStatus::FromError(error)); + *bytes_read = -1; + } + return error == OK; } void URLRequestJob::StopCaching() { @@ -480,11 +481,21 @@ request_->NotifyResponseStarted(); } -void URLRequestJob::NotifyReadComplete(int bytes_read) { +void URLRequestJob::ConvertResultToError(int result, Error* error, int* count) { + if (result >= 0) { + *error = OK; + *count = result; + } else { + *error = static_cast<Error>(result); + *count = 0; + } +} + +void URLRequestJob::ReadRawDataComplete(int result) { // TODO(cbentzel): Remove ScopedTracker below once crbug.com/475755 is fixed. tracked_objects::ScopedTracker tracking_profile( FROM_HERE_WITH_EXPLICIT_FUNCTION( - "475755 URLRequestJob::NotifyReadComplete")); + "475755 URLRequestJob::RawReadCompleted")); if (!request_ || !request_->has_delegate()) return; // The request was destroyed, so there is no more work to do. @@ -497,11 +508,52 @@ // The headers should be complete before reads complete DCHECK(has_handled_response_); - OnRawReadComplete(bytes_read); + Error error; + int bytes_read; + ConvertResultToError(result, &error, &bytes_read); - // Don't notify if we had an error. - if (!request_->status().is_success()) - return; + DCHECK_NE(ERR_IO_PENDING, error); + + // Synchronize the URLRequest state machine with the URLRequestJob state + // machine. If this read succeeded, either the request is at EOF and the + // URLRequest state machine goes to 'finished', or it is not and the + // URLRequest state machine goes to 'success'. If the read failed, the + // URLRequest state machine goes directly to 'finished'. + // + // Update the URLRequest's status first, so that NotifyReadCompleted has an + // accurate view of the request. + if (error == OK && bytes_read > 0) { + SetStatus(URLRequestStatus()); + } else { + NotifyDone(URLRequestStatus::FromError(error)); + } + + GatherRawReadStats(error, bytes_read); + + if (filter_.get() && error == OK) { + int filter_bytes_read = 0; + // Tell the filter that it has more data. + PushInputToFilter(bytes_read); + + // Filter the data. + error = ReadFilteredData(&filter_bytes_read); + + if (error == OK && !filter_bytes_read) + DoneReading(); + + DVLOG(1) << __FUNCTION__ << "() " + << "\"" << (request_ ? request_->url().spec() : "???") << "\"" + << " pre bytes read = " << bytes_read + << " pre total = " << prefilter_bytes_read_ + << " post total = " << postfilter_bytes_read_; + bytes_read = filter_bytes_read; + } else { + DVLOG(1) << __FUNCTION__ << "() " + << "\"" << (request_ ? request_->url().spec() : "???") << "\"" + << " pre bytes read = " << bytes_read + << " pre total = " << prefilter_bytes_read_ + << " post total = " << postfilter_bytes_read_; + } // When notifying the delegate, the delegate can release the request // (and thus release 'this'). After calling to the delegate, we must @@ -510,25 +562,10 @@ // survival until we can get out of this method. scoped_refptr<URLRequestJob> self_preservation(this); - if (filter_.get()) { - // Tell the filter that it has more data - FilteredDataRead(bytes_read); - - // Filter the data. - int filter_bytes_read = 0; - if (ReadFilteredData(&filter_bytes_read)) { - if (!filter_bytes_read) - DoneReading(); - request_->NotifyReadCompleted(filter_bytes_read); - } - } else { + // NotifyReadCompleted should be called after SetStatus or NotifyDone updates + // the status. + if (error == OK) request_->NotifyReadCompleted(bytes_read); - } - DVLOG(1) << __FUNCTION__ << "() " - << "\"" << (request_ ? request_->url().spec() : "???") << "\"" - << " pre bytes read = " << bytes_read - << " pre total = " << prefilter_bytes_read_ - << " post total = " << postfilter_bytes_read_; } void URLRequestJob::NotifyStartError(const URLRequestStatus &status) { @@ -555,7 +592,7 @@ // the response before getting here. DCHECK(has_handled_response_ || !status.is_success()); - // As with NotifyReadComplete, we need to take care to notice if we were + // As with RawReadCompleted, we need to take care to notice if we were // destroyed during a delegate callback. if (request_) { request_->set_is_pending(false); @@ -638,10 +675,8 @@ request_->OnCallToDelegateComplete(); } -bool URLRequestJob::ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) { - DCHECK(bytes_read); - *bytes_read = 0; - return true; +int URLRequestJob::ReadRawData(IOBuffer* buf, int buf_size) { + return 0; } void URLRequestJob::DoneReading() { @@ -651,38 +686,34 @@ void URLRequestJob::DoneReadingRedirectResponse() { } -void URLRequestJob::FilteredDataRead(int bytes_read) { +void URLRequestJob::PushInputToFilter(int bytes_read) { DCHECK(filter_); filter_->FlushStreamBuffer(bytes_read); } -bool URLRequestJob::ReadFilteredData(int* bytes_read) { +Error URLRequestJob::ReadFilteredData(int* bytes_read) { DCHECK(filter_); DCHECK(filtered_read_buffer_.get()); DCHECK_GT(filtered_read_buffer_len_, 0); DCHECK_LT(filtered_read_buffer_len_, 1000000); // Sanity check. - DCHECK(!raw_read_buffer_.get()); + DCHECK(!raw_read_buffer_); *bytes_read = 0; - bool rv = false; + Error error = ERR_FAILED; for (;;) { if (is_done()) - return true; + return OK; if (!filter_needs_more_output_space_ && !filter_->stream_data_len()) { // We don't have any raw data to work with, so read from the transaction. int filtered_data_read; - if (ReadRawDataForFilter(&filtered_data_read)) { - if (filtered_data_read > 0) { - // Give data to filter. - filter_->FlushStreamBuffer(filtered_data_read); - } else { - return true; // EOF. - } - } else { - return false; // IO Pending (or error). - } + error = ReadRawDataForFilter(&filtered_data_read); + // If ReadRawDataForFilter returned some data, fall through to the case + // below; otherwise, return early. + if (error != OK || filtered_data_read == 0) + return error; + filter_->FlushStreamBuffer(filtered_data_read); } if ((filter_->stream_data_len() || filter_needs_more_output_space_) && @@ -708,7 +739,7 @@ filter_needs_more_output_space_ = false; *bytes_read = filtered_data_len; postfilter_bytes_read_ += filtered_data_len; - rv = true; + error = OK; break; } case Filter::FILTER_NEED_MORE_DATA: { @@ -721,7 +752,7 @@ if (filtered_data_len > 0) { *bytes_read = filtered_data_len; postfilter_bytes_read_ += filtered_data_len; - rv = true; + error = OK; } else { // Read again since we haven't received enough data yet (e.g., we // may not have a complete gzip header yet). @@ -732,7 +763,7 @@ case Filter::FILTER_OK: { *bytes_read = filtered_data_len; postfilter_bytes_read_ += filtered_data_len; - rv = true; + error = OK; break; } case Filter::FILTER_ERROR: { @@ -740,21 +771,19 @@ << "\"" << (request_ ? request_->url().spec() : "???") << "\"" << " Filter Error"; filter_needs_more_output_space_ = false; - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - ERR_CONTENT_DECODING_FAILED)); - rv = false; + error = ERR_CONTENT_DECODING_FAILED; break; } default: { NOTREACHED(); filter_needs_more_output_space_ = false; - rv = false; + error = ERR_FAILED; break; } } // If logging all bytes is enabled, log the filtered bytes read. - if (rv && request() && filtered_data_len > 0 && + if (error == OK && request() && filtered_data_len > 0 && request()->net_log().IsCapturing()) { request()->net_log().AddByteTransferEvent( NetLog::TYPE_URL_REQUEST_JOB_FILTERED_BYTES_READ, filtered_data_len, @@ -762,18 +791,18 @@ } } else { // we are done, or there is no data left. - rv = true; + error = OK; } break; } - if (rv) { + if (error == OK) { // When we successfully finished a read, we no longer need to save the // caller's buffers. Release our reference. filtered_read_buffer_ = NULL; filtered_read_buffer_len_ = 0; } - return rv; + return error; } void URLRequestJob::DestroyFilters() { @@ -806,9 +835,8 @@ request_->proxy_server_ = proxy_server; } -bool URLRequestJob::ReadRawDataForFilter(int* bytes_read) { - bool rv = false; - +Error URLRequestJob::ReadRawDataForFilter(int* bytes_read) { + Error error = ERR_FAILED; DCHECK(bytes_read); DCHECK(filter_.get()); @@ -820,30 +848,28 @@ if (!filter_->stream_data_len() && !is_done()) { IOBuffer* stream_buffer = filter_->stream_buffer(); int stream_buffer_size = filter_->stream_buffer_size(); - rv = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read); + error = ReadRawDataHelper(stream_buffer, stream_buffer_size, bytes_read); } - return rv; + return error; } -bool URLRequestJob::ReadRawDataHelper(IOBuffer* buf, - int buf_size, - int* bytes_read) { - DCHECK(!request_->status().is_io_pending()); - DCHECK(raw_read_buffer_.get() == NULL); +Error URLRequestJob::ReadRawDataHelper(IOBuffer* buf, + int buf_size, + int* bytes_read) { + DCHECK(!raw_read_buffer_); - // Keep a pointer to the read buffer, so we have access to it in the - // OnRawReadComplete() callback in the event that the read completes - // asynchronously. + // Keep a pointer to the read buffer, so we have access to it in + // GatherRawReadStats() in the event that the read completes asynchronously. raw_read_buffer_ = buf; - bool rv = ReadRawData(buf, buf_size, bytes_read); + Error error; + ConvertResultToError(ReadRawData(buf, buf_size), &error, bytes_read); - if (!request_->status().is_io_pending()) { - // If the read completes synchronously, either success or failure, - // invoke the OnRawReadComplete callback so we can account for the - // completed read. - OnRawReadComplete(*bytes_read); + if (error != ERR_IO_PENDING) { + // If the read completes synchronously, either success or failure, invoke + // GatherRawReadStats so we can account for the completed read. + GatherRawReadStats(error, *bytes_read); } - return rv; + return error; } void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) { @@ -852,9 +878,16 @@ NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); } -void URLRequestJob::OnRawReadComplete(int bytes_read) { - DCHECK(raw_read_buffer_.get()); - // If |filter_| is non-NULL, bytes will be logged after it is applied instead. +void URLRequestJob::GatherRawReadStats(Error error, int bytes_read) { + DCHECK(raw_read_buffer_ || bytes_read == 0); + DCHECK_NE(ERR_IO_PENDING, error); + + if (error != OK) { + raw_read_buffer_ = nullptr; + return; + } + // If |filter_| is non-NULL, bytes will be logged after it is applied + // instead. if (!filter_.get() && request() && bytes_read > 0 && request()->net_log().IsCapturing()) { request()->net_log().AddByteTransferEvent( @@ -865,7 +898,7 @@ if (bytes_read > 0) { RecordBytesRead(bytes_read); } - raw_read_buffer_ = NULL; + raw_read_buffer_ = nullptr; } void URLRequestJob::RecordBytesRead(int bytes_read) {
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index f010913..83358f361 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h
@@ -17,6 +17,7 @@ #include "base/power_monitor/power_observer.h" #include "net/base/host_port_pair.h" #include "net/base/load_states.h" +#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/base/request_priority.h" #include "net/base/upload_progress.h" @@ -278,23 +279,9 @@ // Notifies the job that headers have been received. void NotifyHeadersComplete(); - // Notifies the request that the job has completed a Read operation. - void NotifyReadComplete(int bytes_read); - // Notifies the request that a start error has occurred. void NotifyStartError(const URLRequestStatus& status); - // NotifyDone marks when we are done with a request. It is really - // a glorified set_status, but also does internal state checking and - // job tracking. It should be called once per request, when the job is - // finished doing all IO. - void NotifyDone(const URLRequestStatus& status); - - // Some work performed by NotifyDone must be completed on a separate task - // so as to avoid re-entering the delegate. This method exists to perform - // that work. - void CompleteNotifyDone(); - // Used as an asynchronous callback for Kill to notify the URLRequest // that we were canceled. void NotifyCanceled(); @@ -307,17 +294,19 @@ void OnCallToDelegate(); void OnCallToDelegateComplete(); - // Called to read raw (pre-filtered) data from this Job. - // If returning true, data was read from the job. buf will contain - // the data, and bytes_read will receive the number of bytes read. - // If returning true, and bytes_read is returned as 0, there is no - // additional data to be read. - // If returning false, an error occurred or an async IO is now pending. - // If async IO is pending, the status of the request will be - // URLRequestStatus::IO_PENDING, and buf must remain available until the - // operation is completed. See comments on URLRequest::Read for more - // info. - virtual bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read); + // Called to read raw (pre-filtered) data from this Job. Reads at most + // |buf_size| bytes into |buf|. + // Possible return values: + // >= 0: Read completed synchronously. Return value is the number of bytes + // read. 0 means eof. + // ERR_IO_PENDING: Read pending asynchronously. + // When the read completes, |ReadRawDataComplete| should be + // called. + // Any other negative number: Read failed synchronously. Return value is a + // network error code. + // This method might hold onto a reference to |buf| (by incrementing the + // refcount) until the method completes or is cancelled. + virtual int ReadRawData(IOBuffer* buf, int buf_size); // Called to tell the job that a filter has successfully reached the end of // the stream. @@ -328,14 +317,14 @@ // bodies are never read. virtual void DoneReadingRedirectResponse(); - // Informs the filter that data has been read into its buffer - void FilteredDataRead(int bytes_read); - - // Reads filtered data from the request. Returns true if successful, - // false otherwise. Note, if there is not enough data received to - // return data, this call can issue a new async IO request under - // the hood. - bool ReadFilteredData(int* bytes_read); + // Reads filtered data from the request. Returns OK if immediately successful, + // ERR_IO_PENDING if the request couldn't complete synchronously, and some + // other error code if the request failed synchronously. Note that this + // function can issue new asynchronous requests if needed, in which case it + // returns ERR_IO_PENDING. If this method completes synchronously, + // |*bytes_read| is the number of bytes output by the filter chain if this + // method returns OK, or zero if this method returns an error. + Error ReadFilteredData(int* bytes_read); // Whether the response is being filtered in this job. // Only valid after NotifyHeadersComplete() has been called. @@ -367,19 +356,33 @@ // reflects bytes read even when there is no filter. int64 postfilter_bytes_read() const { return postfilter_bytes_read_; } + // Turns an integer result code into an Error and a count of bytes read. + // The semantics are: + // |result| >= 0: |*error| == OK, |*count| == |result| + // |result| < 0: |*error| = |result|, |*count| == 0 + static void ConvertResultToError(int result, Error* error, int* count); + + // Completion callback for raw reads. See |ReadRawData| for details. + // |bytes_read| is either >= 0 to indicate a successful read and count of + // bytes read, or < 0 to indicate an error. + void ReadRawDataComplete(int bytes_read); + // The request that initiated this job. This value MAY BE NULL if the // request was released by DetachRequest(). URLRequest* request_; private: // When data filtering is enabled, this function is used to read data - // for the filter. Returns true if raw data was read. Returns false if - // an error occurred (or we are waiting for IO to complete). - bool ReadRawDataForFilter(int* bytes_read); + // for the filter. Returns a net error code to indicate if raw data was + // successfully read, an error happened, or the IO is pending. + Error ReadRawDataForFilter(int* bytes_read); + + // Informs the filter chain that data has been read into its buffer. + void PushInputToFilter(int bytes_read); // Invokes ReadRawData and records bytes read if the read completes // synchronously. - bool ReadRawDataHelper(IOBuffer* buf, int buf_size, int* bytes_read); + Error ReadRawDataHelper(IOBuffer* buf, int buf_size, int* bytes_read); // Called in response to a redirect that was not canceled to follow the // redirect. The current job will be replaced with a new job loading the @@ -388,9 +391,9 @@ // Called after every raw read. If |bytes_read| is > 0, this indicates // a successful read of |bytes_read| unfiltered bytes. If |bytes_read| - // is 0, this indicates that there is no additional data to read. If - // |bytes_read| is < 0, an error occurred and no bytes were read. - void OnRawReadComplete(int bytes_read); + // is 0, this indicates that there is no additional data to read. |error| + // specifies whether an error occurred and no bytes were read. + void GatherRawReadStats(Error error, int bytes_read); // Updates the profiling info and notifies observers that an additional // |bytes_read| unfiltered bytes have been read for this job. @@ -400,6 +403,16 @@ // out. bool FilterHasData(); + // NotifyDone marks that request is done. It is really a glorified + // set_status, but also does internal state checking and job tracking. It + // should be called once per request, when the job is finished doing all IO. + void NotifyDone(const URLRequestStatus& status); + + // Some work performed by NotifyDone must be completed asynchronously so + // as to avoid re-entering URLRequest::Delegate. This method performs that + // work. + void CompleteNotifyDone(); + // Subclasses may implement this method to record packet arrival times. // The default implementation does nothing. Only invoked when bytes have been // read since the last invocation.
diff --git a/net/url_request/url_request_job_unittest.cc b/net/url_request/url_request_job_unittest.cc index f9ea1fe..62b09f1c 100644 --- a/net/url_request/url_request_job_unittest.cc +++ b/net/url_request/url_request_job_unittest.cc
@@ -20,6 +20,10 @@ const char kGzipData[] = "\x1f\x08b\x08\0\0\0\0\0\0\3\3\0\0\0\0\0\0\0\0"; const char kGzipDataWithName[] = "\x1f\x08b\x08\x08\0\0\0\0\0\0name\0\3\0\0\0\0\0\0\0\0"; +// Gzip data that contains the word hello with a newline character. +const char kGzipHelloData[] = + "\x1f\x8b\x08\x08\x46\x7d\x4e\x56\x00\x03\x67\x7a\x69\x70\x2e\x74\x78\x74" + "\x00\xcb\x48\xcd\xc9\xc9\xe7\x02\x00\x20\x30\x3a\x36\x06\x00\x00\x00"; void GZipServer(const HttpRequestInfo* request, std::string* response_status, @@ -28,6 +32,13 @@ response_data->assign(kGzipData, sizeof(kGzipData)); } +void GZipHelloServer(const HttpRequestInfo* request, + std::string* response_status, + std::string* response_headers, + std::string* response_data) { + response_data->assign(kGzipHelloData, sizeof(kGzipHelloData)); +} + void BigGZipServer(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, @@ -56,6 +67,14 @@ OK, }; +const MockTransaction kGzip_Slow_Transaction = { + "http://www.google.com/gzyp", "GET", base::Time(), "", LOAD_NORMAL, + "HTTP/1.1 200 OK", + "Cache-Control: max-age=10000\n" + "Content-Encoding: gzip\n", + base::Time(), "", TEST_MODE_SLOW_READ, &GZipHelloServer, nullptr, 0, 0, OK, +}; + const MockTransaction kRedirect_Transaction = { "http://www.google.com/redirect", "GET", @@ -76,6 +95,24 @@ OK, }; +const MockTransaction kEmptyBodyGzip_Transaction = { + "http://www.google.com/empty_body", + "GET", + base::Time(), + "", + LOAD_NORMAL, + "HTTP/1.1 200 OK", + "Content-Encoding: gzip\n", + base::Time(), + "", + TEST_MODE_NORMAL, + nullptr, + nullptr, + 0, + 0, + OK, +}; + } // namespace TEST(URLRequestJob, TransactionNotifiedWhenDone) { @@ -187,4 +224,54 @@ RemoveMockTransaction(&kGZip_Transaction); } +// Makes sure that ReadRawDataComplete correctly updates request status before +// calling ReadFilteredData. +// Regression test for crbug.com/553300. +TEST(URLRequestJob, EmptyBodySkipFilter) { + MockNetworkLayer network_layer; + TestURLRequestContext context; + context.set_http_transaction_factory(&network_layer); + + TestDelegate d; + scoped_ptr<URLRequest> req(context.CreateRequest( + GURL(kEmptyBodyGzip_Transaction.url), DEFAULT_PRIORITY, &d)); + AddMockTransaction(&kEmptyBodyGzip_Transaction); + + req->set_method("GET"); + req->Start(); + + base::MessageLoop::current()->Run(); + + EXPECT_FALSE(d.request_failed()); + EXPECT_EQ(200, req->GetResponseCode()); + EXPECT_TRUE(d.data_received().empty()); + EXPECT_TRUE(network_layer.done_reading_called()); + + RemoveMockTransaction(&kEmptyBodyGzip_Transaction); +} + +// Regression test for crbug.com/553300. +TEST(URLRequestJob, SlowFilterRead) { + MockNetworkLayer network_layer; + TestURLRequestContext context; + context.set_http_transaction_factory(&network_layer); + + TestDelegate d; + scoped_ptr<URLRequest> req(context.CreateRequest( + GURL(kGzip_Slow_Transaction.url), DEFAULT_PRIORITY, &d)); + AddMockTransaction(&kGzip_Slow_Transaction); + + req->set_method("GET"); + req->Start(); + + base::MessageLoop::current()->Run(); + + EXPECT_FALSE(d.request_failed()); + EXPECT_EQ(200, req->GetResponseCode()); + EXPECT_EQ("hello\n", d.data_received()); + EXPECT_TRUE(network_layer.done_reading_called()); + + RemoveMockTransaction(&kGzip_Slow_Transaction); +} + } // namespace net
diff --git a/net/url_request/url_request_simple_job.cc b/net/url_request/url_request_simple_job.cc index bc15079..c12555d4 100644 --- a/net/url_request/url_request_simple_job.cc +++ b/net/url_request/url_request_simple_job.cc
@@ -65,33 +65,20 @@ URLRequestSimpleJob::~URLRequestSimpleJob() {} -bool URLRequestSimpleJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { - DCHECK(bytes_read); - buf_size = static_cast<int>( - std::min(static_cast<int64>(buf_size), - byte_range_.last_byte_position() - next_data_offset_ + 1)); - DCHECK_GE(buf_size, 0); - if (buf_size == 0) { - *bytes_read = 0; - return true; - } +int URLRequestSimpleJob::ReadRawData(IOBuffer* buf, int buf_size) { + buf_size = std::min(static_cast<int64>(buf_size), + byte_range_.last_byte_position() - next_data_offset_ + 1); + if (buf_size == 0) + return 0; // Do memory copy on a background thread. See crbug.com/422489. GetTaskRunner()->PostTaskAndReply( FROM_HERE, base::Bind(&CopyData, make_scoped_refptr(buf), buf_size, data_, next_data_offset_), - base::Bind(&URLRequestSimpleJob::OnReadCompleted, + base::Bind(&URLRequestSimpleJob::ReadRawDataComplete, weak_factory_.GetWeakPtr(), buf_size)); next_data_offset_ += buf_size; - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - return false; -} - -void URLRequestSimpleJob::OnReadCompleted(int bytes_read) { - SetStatus(URLRequestStatus()); - NotifyReadComplete(bytes_read); + return ERR_IO_PENDING; } base::TaskRunner* URLRequestSimpleJob::GetTaskRunner() const { @@ -122,8 +109,8 @@ return; if (ranges().size() > 1) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -143,8 +130,8 @@ if (result == OK) { // Notify that the headers are complete if (!byte_range_.ComputeBounds(data_->size())) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, - ERR_REQUEST_RANGE_NOT_SATISFIABLE)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; }
diff --git a/net/url_request/url_request_simple_job.h b/net/url_request/url_request_simple_job.h index 6c9d5e8..06f718e 100644 --- a/net/url_request/url_request_simple_job.h +++ b/net/url_request/url_request_simple_job.h
@@ -28,7 +28,7 @@ void Start() override; void Kill() override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; bool GetMimeType(std::string* mime_type) const override; bool GetCharset(std::string* charset) override; @@ -66,7 +66,6 @@ private: void OnGetDataCompleted(int result); - void OnReadCompleted(int bytes_read); HttpByteRange byte_range_; std::string mime_type_;
diff --git a/net/url_request/url_request_status.cc b/net/url_request/url_request_status.cc index 2a6a2fa..7207df2f 100644 --- a/net/url_request/url_request_status.cc +++ b/net/url_request/url_request_status.cc
@@ -46,4 +46,19 @@ } } +Error URLRequestStatus::ToNetError() const { + switch (status_) { + case SUCCESS: + return OK; + case IO_PENDING: + return ERR_IO_PENDING; + case CANCELED: + return ERR_ABORTED; + case FAILED: + return static_cast<Error>(error_); + } + NOTREACHED(); + return ERR_FAILED; +} + } // namespace net
diff --git a/net/url_request/url_request_status.h b/net/url_request/url_request_status.h index 44a5d22b..694c5100 100644 --- a/net/url_request/url_request_status.h +++ b/net/url_request/url_request_status.h
@@ -5,6 +5,7 @@ #ifndef NET_URL_REQUEST_URL_REQUEST_STATUS_H_ #define NET_URL_REQUEST_URL_REQUEST_STATUS_H_ +#include "net/base/net_errors.h" #include "net/base/net_export.h" namespace net { @@ -41,6 +42,13 @@ // deprecated. See https://crbug.com/490311. static URLRequestStatus FromError(int error); + // Returns a Error corresponding to |status_|. + // OK for OK + // ERR_IO_PENDING for IO_PENDING + // ERR_ABORTED for CANCELLED + // Error for FAILED + Error ToNetError() const; + Status status() const { return status_; } int error() const { return error_; }
diff --git a/net/url_request/url_request_test_job.cc b/net/url_request/url_request_test_job.cc index 8a293c38..bd1c9052 100644 --- a/net/url_request/url_request_test_job.cc +++ b/net/url_request/url_request_test_job.cc
@@ -210,7 +210,8 @@ // unexpected url, return error // FIXME(brettw) we may want to use WININET errors or have some more types // of errors - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, ERR_INVALID_URL)); + NotifyStartError( + URLRequestStatus(URLRequestStatus::FAILED, ERR_INVALID_URL)); // FIXME(brettw): this should emulate a network error, and not just fail // initiating a connection return; @@ -222,22 +223,15 @@ this->NotifyHeadersComplete(); } -bool URLRequestTestJob::ReadRawData(IOBuffer* buf, - int buf_size, - int* bytes_read) { +int URLRequestTestJob::ReadRawData(IOBuffer* buf, int buf_size) { if (stage_ == WAITING) { async_buf_ = buf; async_buf_size_ = buf_size; - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - return false; + return ERR_IO_PENDING; } - DCHECK(bytes_read); - *bytes_read = 0; - - if (offset_ >= static_cast<int>(response_data_.length())) { - return true; // done reading - } + if (offset_ >= static_cast<int>(response_data_.length())) + return 0; // done reading int to_read = buf_size; if (to_read + offset_ > static_cast<int>(response_data_.length())) @@ -246,8 +240,7 @@ memcpy(buf->data(), &response_data_.c_str()[offset_], to_read); offset_ += to_read; - *bytes_read = to_read; - return true; + return to_read; } void URLRequestTestJob::GetResponseInfo(HttpResponseInfo* info) { @@ -305,16 +298,15 @@ stage_ = DATA_AVAILABLE; // OK if ReadRawData wasn't called yet. if (async_buf_) { - int bytes_read; - if (!ReadRawData(async_buf_, async_buf_size_, &bytes_read)) - NOTREACHED() << "This should not return false in DATA_AVAILABLE."; - SetStatus(URLRequestStatus()); // clear the io pending flag + int result = ReadRawData(async_buf_, async_buf_size_); + if (result < 0) + NOTREACHED() << "Reads should not fail in DATA_AVAILABLE."; if (NextReadAsync()) { // Make all future reads return io pending until the next // ProcessNextOperation(). stage_ = WAITING; } - NotifyReadComplete(bytes_read); + ReadRawDataComplete(result); } break; case DATA_AVAILABLE:
diff --git a/net/url_request/url_request_test_job.h b/net/url_request/url_request_test_job.h index 09b31a4..eb1db01 100644 --- a/net/url_request/url_request_test_job.h +++ b/net/url_request/url_request_test_job.h
@@ -111,7 +111,7 @@ // Job functions void SetPriority(RequestPriority priority) override; void Start() override; - bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(IOBuffer* buf, int buf_size) override; void Kill() override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(HttpResponseInfo* info) override;
diff --git a/pdf/document_loader.h b/pdf/document_loader.h index 148aaf19..4e734a0 100644 --- a/pdf/document_loader.h +++ b/pdf/document_loader.h
@@ -47,7 +47,7 @@ const std::string& url, const std::string& headers); - // Data access interface. Return true is sucessful. + // Data access interface. Return true is successful. bool GetBlock(uint32_t position, uint32_t size, void* buf) const; // Data availability interface. Return true data avaialble.
diff --git a/ppapi/api/ppb_compositor.idl b/ppapi/api/ppb_compositor.idl index 0fb62b38..d9b4e64 100644 --- a/ppapi/api/ppb_compositor.idl +++ b/ppapi/api/ppb_compositor.idl
@@ -84,7 +84,7 @@ * of a module. * * @return A <code>PP_Resource</code> containing the compositor resource if - * sucessful or 0 otherwise. + * successful or 0 otherwise. */ PP_Resource Create([in] PP_Instance instance); @@ -102,7 +102,7 @@ * a compositor layer resource. * * @return A <code>PP_Resource</code> containing the compositor layer - * resource if sucessful or 0 otherwise. + * resource if successful or 0 otherwise. */ PP_Resource AddLayer([in] PP_Resource compositor);
diff --git a/ppapi/c/ppb_compositor.h b/ppapi/c/ppb_compositor.h index 18c9760..ce58ab4 100644 --- a/ppapi/c/ppb_compositor.h +++ b/ppapi/c/ppb_compositor.h
@@ -98,7 +98,7 @@ * of a module. * * @return A <code>PP_Resource</code> containing the compositor resource if - * sucessful or 0 otherwise. + * successful or 0 otherwise. */ PP_Resource (*Create)(PP_Instance instance); /** @@ -115,7 +115,7 @@ * a compositor layer resource. * * @return A <code>PP_Resource</code> containing the compositor layer - * resource if sucessful or 0 otherwise. + * resource if successful or 0 otherwise. */ PP_Resource (*AddLayer)(PP_Resource compositor); /**
diff --git a/ppapi/proxy/video_encoder_resource_unittest.cc b/ppapi/proxy/video_encoder_resource_unittest.cc index c1d3908..d4d9e1c 100644 --- a/ppapi/proxy/video_encoder_resource_unittest.cc +++ b/ppapi/proxy/video_encoder_resource_unittest.cc
@@ -643,7 +643,7 @@ TEST_F(VideoEncoderResourceTest, InitializeSuccess) { { // Verify the initialize callback is called when initialization is - // successfull. + // successful. LockingResourceReleaser encoder(CreateEncoder()); ResourceMessageCallParams params; PP_Size size = kFrameSize;
diff --git a/printing/backend/print_backend_cups.cc b/printing/backend/print_backend_cups.cc index 58ae20f..2b1033e 100644 --- a/printing/backend/print_backend_cups.cc +++ b/printing/backend/print_backend_cups.cc
@@ -4,8 +4,6 @@ #include "printing/backend/print_backend.h" -#include "build/build_config.h" - #include <dlfcn.h> #include <errno.h> #include <pthread.h> @@ -269,7 +267,8 @@ // here. // Note: After looking at CUPS sources, it looks like non-blocking // connection will timeout after 10 seconds of no data period. And it will - // return the same way as if data was completely and sucessfully downloaded. + // return the same way as if data was completely and successfully + // downloaded. HttpConnectionCUPS http(print_server_url_, cups_encryption_); http.SetBlocking(blocking_); ppd_file_path = cupsGetPPD2(http.http(), name);
diff --git a/printing/metafile_skia_wrapper.cc b/printing/metafile_skia_wrapper.cc index 90a9c7c..9df35ef 100644 --- a/printing/metafile_skia_wrapper.cc +++ b/printing/metafile_skia_wrapper.cc
@@ -5,10 +5,10 @@ #include "printing/metafile_skia_wrapper.h" #include "skia/ext/platform_device.h" #include "skia/ext/refptr.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkDevice.h" #include "third_party/skia/include/core/SkMetaData.h" +class SkCanvas; + namespace printing { namespace {
diff --git a/printing/pdf_metafile_skia.h b/printing/pdf_metafile_skia.h index 6bc1220..a315fa9 100644 --- a/printing/pdf_metafile_skia.h +++ b/printing/pdf_metafile_skia.h
@@ -16,8 +16,6 @@ #include <windows.h> #endif -class SkBaseDevice; - #if defined(OS_CHROMEOS) || defined(OS_ANDROID) namespace base { struct FileDescriptor;
diff --git a/remoting/android/java/res/drawable-hdpi/ic_menu.png b/remoting/android/java/res/drawable-hdpi/ic_menu.png new file mode 100644 index 0000000..3f8ebd6 --- /dev/null +++ b/remoting/android/java/res/drawable-hdpi/ic_menu.png Binary files differ
diff --git a/remoting/android/java/res/drawable-mdpi/ic_menu.png b/remoting/android/java/res/drawable-mdpi/ic_menu.png new file mode 100644 index 0000000..ef2a48c --- /dev/null +++ b/remoting/android/java/res/drawable-mdpi/ic_menu.png Binary files differ
diff --git a/remoting/android/java/res/drawable-xhdpi/ic_menu.png b/remoting/android/java/res/drawable-xhdpi/ic_menu.png new file mode 100644 index 0000000..4e0286b --- /dev/null +++ b/remoting/android/java/res/drawable-xhdpi/ic_menu.png Binary files differ
diff --git a/remoting/android/java/res/drawable-xxhdpi/ic_menu.png b/remoting/android/java/res/drawable-xxhdpi/ic_menu.png new file mode 100644 index 0000000..7dae60b4 --- /dev/null +++ b/remoting/android/java/res/drawable-xxhdpi/ic_menu.png Binary files differ
diff --git a/remoting/android/java/res/drawable-xxxhdpi/ic_menu.png b/remoting/android/java/res/drawable-xxxhdpi/ic_menu.png new file mode 100644 index 0000000..5c747ed --- /dev/null +++ b/remoting/android/java/res/drawable-xxxhdpi/ic_menu.png Binary files differ
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java index bf7dd02..5dce18ed 100644 --- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java +++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -11,12 +11,15 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.provider.Settings; +import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -26,6 +29,7 @@ import android.widget.ListView; import android.widget.Toast; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Log; import org.chromium.chromoting.accountswitcher.AccountSwitcher; import org.chromium.chromoting.accountswitcher.AccountSwitcherFactory; @@ -185,10 +189,44 @@ findViewById(R.id.host_setup_link_android).setOnClickListener(this); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, + mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.open_navigation_drawer, R.string.close_navigation_drawer); mDrawerLayout.setDrawerListener(mDrawerToggle); + // Disable the hamburger icon animation. This is more complex than it ought to be. + // The animation can be customized by tweaking some style parameters - see + // http://developer.android.com/reference/android/support/v7/appcompat/R.styleable.html#DrawerArrowToggle . + // But these can't disable the animation completely. + // The icon can only be changed by disabling the drawer indicator, which has side-effects + // that must be worked around. It disables the built-in click listener, so this has to be + // implemented and added. This also requires that the toolbar be passed to the + // ActionBarDrawerToggle ctor above (otherwise the listener is ignored and warnings are + // logged). + // Also, the animation itself is a private implementation detail - it is not possible to + // simply access the first frame of the animation. And the hamburger menu icon doesn't + // exist as a builtin Android resource, so it has to be provided as an application + // resource instead (R.drawable.ic_menu). And, on Lollipop devices and above, it should be + // tinted to match the colorControlNormal theme attribute. + mDrawerToggle.setDrawerIndicatorEnabled(false); + mDrawerToggle.setToolbarNavigationClickListener( + new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mDrawerLayout.isDrawerOpen(Gravity.START)) { + mDrawerLayout.closeDrawer(Gravity.START); + } else { + mDrawerLayout.openDrawer(Gravity.START); + } + } + }); + + // Set the three-line icon instead of the default which is a tinted arrow icon. + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + Drawable menuIcon = ApiCompatibilityUtils.getDrawable(getResources(), R.drawable.ic_menu); + DrawableCompat.setTint(menuIcon.mutate(), + ChromotingUtil.getColorAttribute(this, R.attr.colorControlNormal)); + getSupportActionBar().setHomeAsUpIndicator(menuIcon); + ListView navigationMenu = new ListView(this); navigationMenu.setChoiceMode(ListView.CHOICE_MODE_SINGLE); navigationMenu.setLayoutParams(new LinearLayout.LayoutParams( @@ -211,9 +249,6 @@ } }); - // Make the navigation drawer icon visible in the ActionBar. - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - mAccountSwitcher = AccountSwitcherFactory.getInstance().createAccountSwitcher(this, this); mAccountSwitcher.setNavigation(navigationMenu); LinearLayout navigationDrawer = (LinearLayout) findViewById(R.id.navigation_drawer);
diff --git a/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java b/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java index 5224801..64e0008 100644 --- a/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java +++ b/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java
@@ -5,13 +5,13 @@ package org.chromium.chromoting; import android.content.Context; +import android.content.res.Resources; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.TypedValue; import android.view.Menu; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.Log; /** Utility methods for chromoting code. */ public abstract class ChromotingUtil { @@ -24,26 +24,7 @@ * @param menu Menu with icons to be tinted. */ public static void tintMenuIcons(Context context, Menu menu) { - TypedValue typedValue = new TypedValue(); - if (!context.getTheme().resolveAttribute(R.attr.colorControlNormal, typedValue, true)) { - Log.e(TAG, "Failed to resolve colorControlNormal attribute."); - return; - } - - int color; - if (typedValue.resourceId != 0) { - // Attribute is a resource. - color = ApiCompatibilityUtils.getColor(context.getResources(), typedValue.resourceId); - } else if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT - && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) { - // Attribute is a raw color value. - color = typedValue.data; - } else { - // The resource compiler should prevent this from happening. - Log.e(TAG, "Invalid colorControlNormal attribute: %s", typedValue); - return; - } - + int color = getColorAttribute(context, R.attr.colorControlNormal); int items = menu.size(); for (int i = 0; i < items; i++) { Drawable icon = menu.getItem(i).getIcon(); @@ -52,4 +33,29 @@ } } } + + /** + * Returns a color from a theme attribute. + * @param context Context with resources to look up. + * @param attribute Attribute such as R.attr.colorControlNormal. + * @return Color value. + * @throws Resources.NotFoundException + */ + public static int getColorAttribute(Context context, int attribute) { + TypedValue typedValue = new TypedValue(); + if (!context.getTheme().resolveAttribute(attribute, typedValue, true)) { + throw new Resources.NotFoundException("Attribute not found."); + } + + if (typedValue.resourceId != 0) { + // Attribute is a resource. + return ApiCompatibilityUtils.getColor(context.getResources(), typedValue.resourceId); + } else if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT + && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) { + // Attribute is a raw color value. + return typedValue.data; + } else { + throw new Resources.NotFoundException("Attribute not a color."); + } + } }
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java index 5e4cd5e1..69dbdba2 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
@@ -9,6 +9,7 @@ import android.graphics.Point; import android.os.Looper; +import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -141,21 +142,21 @@ private static CapabilityManager sCapabilityManager = CapabilityManager.getInstance(); /** - * To be called once from the main Activity. Any subsequent calls will update the application - * context, but not reload the library. This is useful e.g. when the activity is closed and the - * user later wants to return to the application. Called on the UI thread. + * To be called once from the main Activity. Loads and initializes the native code. + * Called on the UI thread. */ public static void loadLibrary(Context context) { if (sLoaded) return; System.loadLibrary("remoting_client_jni"); - nativeLoadNative(context); + ContextUtils.initApplicationContext(context.getApplicationContext()); + nativeLoadNative(); sLoaded = true; } /** Performs the native portion of the initialization. */ - private static native void nativeLoadNative(Context context); + private static native void nativeLoadNative(); /* * API/OAuth2 keys access.
diff --git a/remoting/client/jni/chromoting_jni_runtime.cc b/remoting/client/jni/chromoting_jni_runtime.cc index af778c38..335e1ff 100644 --- a/remoting/client/jni/chromoting_jni_runtime.cc +++ b/remoting/client/jni/chromoting_jni_runtime.cc
@@ -38,11 +38,7 @@ // Implementation of stubs defined in JniInterface_jni.h. These are the entry // points for JNI calls from Java into C++. -static void LoadNative(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - const JavaParamRef<jobject>& context) { - base::android::InitApplicationContext(env, context); - +static void LoadNative(JNIEnv* env, const JavaParamRef<jclass>& clazz) { // The google_apis functions check the command-line arguments to make sure no // runtime API keys have been specified by the environment. Unfortunately, we // neither launch Chromium nor have a command line, so we need to prevent
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 9bfc393..1f1e96c2 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -206,8 +206,6 @@ testonly = true sources = [ - "fake_desktop_capturer.cc", - "fake_desktop_capturer.h", "fake_desktop_environment.cc", "fake_desktop_environment.h", "fake_host_extension.cc", @@ -250,7 +248,6 @@ "audio_pump_unittest.cc", "audio_silence_detector_unittest.cc", "backoff_timer_unittest.cc", - "capture_scheduler_unittest.cc", "chromeos/aura_desktop_capturer_unittest.cc", "chromeos/clipboard_aura_unittest.cc", "chromoting_host_context_unittest.cc", @@ -295,7 +292,6 @@ "third_party_auth_config_unittest.cc", "token_validator_factory_impl_unittest.cc", "touch_injector_win_unittest.cc", - "video_frame_pump_unittest.cc", "video_frame_recorder_unittest.cc", "win/rdp_client_unittest.cc", "win/worker_process_launcher_unittest.cc",
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 43bcabbd7..4eb7de8f 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc
@@ -79,8 +79,6 @@ signal_strategy_(signal_strategy), started_(false), login_backoff_(&kDefaultBackoffPolicy), - authenticating_client_(false), - reject_authenticating_client_(false), enable_curtaining_(false), weak_factory_(this) { DCHECK(network_task_runner_->BelongsToCurrentThread()); @@ -133,11 +131,6 @@ extensions_.push_back(extension.release()); } -void ChromotingHost::RejectAuthenticatingClient() { - DCHECK(authenticating_client_); - reject_authenticating_client_ = true; -} - void ChromotingHost::SetAuthenticatorFactory( scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) { DCHECK(CalledOnValidThread()); @@ -183,7 +176,7 @@ login_backoff_.InformOfRequest(false); } -bool ChromotingHost::OnSessionAuthenticated(ClientSession* client) { +void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { DCHECK(CalledOnValidThread()); login_backoff_.Reset(); @@ -192,10 +185,16 @@ // is called to avoid it becoming invalid when the client is removed from // the list. ClientList::iterator it = clients_.begin(); + base::WeakPtr<ChromotingHost> self = weak_factory_.GetWeakPtr(); while (it != clients_.end()) { ClientSession* other_client = *it++; - if (other_client != client) + if (other_client != client) { other_client->DisconnectSession(protocol::OK); + + // Quit if the host was destroyed. + if (!self) + return; + } } // Disconnects above must have destroyed all other clients. @@ -204,14 +203,8 @@ // Notify observers that there is at least one authenticated client. const std::string& jid = client->client_jid(); - reject_authenticating_client_ = false; - - authenticating_client_ = true; FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnClientAuthenticated(jid)); - authenticating_client_ = false; - - return !reject_authenticating_client_; } void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { @@ -236,13 +229,15 @@ ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); CHECK(it != clients_.end()); - if (client->is_authenticated()) { - FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, - OnClientDisconnected(client->client_jid())); - } - + bool was_authenticated = client->is_authenticated(); + std::string jid = client->client_jid(); clients_.erase(it); delete client; + + if (was_authenticated) { + FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, + OnClientDisconnected(jid)); + } } void ChromotingHost::OnSessionRouteChange(
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index 2947452..6479f5d 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h
@@ -94,11 +94,6 @@ // Registers a host extension. void AddExtension(scoped_ptr<HostExtension> extension); - // This method may be called only from - // HostStatusObserver::OnClientAuthenticated() to reject the new - // client. - void RejectAuthenticatingClient(); - // Sets the authenticator factory to use for incoming // connections. Incoming connections are rejected until // authenticator factory is set. Must be called on the network @@ -119,7 +114,7 @@ //////////////////////////////////////////////////////////////////////////// // ClientSession::EventHandler implementation. void OnSessionAuthenticating(ClientSession* client) override; - bool OnSessionAuthenticated(ClientSession* client) override; + void OnSessionAuthenticated(ClientSession* client) override; void OnSessionChannelsConnected(ClientSession* client) override; void OnSessionAuthenticationFailed(ClientSession* client) override; void OnSessionClosed(ClientSession* session) override; @@ -186,10 +181,6 @@ // Login backoff state. net::BackoffEntry login_backoff_; - // Flags used for RejectAuthenticatingClient(). - bool authenticating_client_; - bool reject_authenticating_client_; - // True if the curtain mode is enabled. bool enable_curtaining_;
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index e820223..cd54719 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc
@@ -10,11 +10,11 @@ #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" #include "remoting/host/desktop_environment.h" -#include "remoting/host/fake_desktop_capturer.h" #include "remoting/host/fake_mouse_cursor_monitor.h" #include "remoting/host/host_mock_objects.h" #include "remoting/proto/video.pb.h" #include "remoting/protocol/errors.h" +#include "remoting/protocol/fake_desktop_capturer.h" #include "remoting/protocol/protocol_mock_objects.h" #include "remoting/protocol/session_config.h" #include "remoting/signaling/mock_signal_strategy.h" @@ -252,7 +252,7 @@ // Creates a fake webrtc::DesktopCapturer, to mock // DesktopEnvironment::CreateVideoCapturer(). webrtc::DesktopCapturer* CreateVideoCapturer() { - return new FakeDesktopCapturer(); + return new protocol::FakeDesktopCapturer(); } // Creates a MockMouseCursorMonitor, to mock @@ -270,11 +270,6 @@ NotifyClientSessionClosed(0); } - // Notify |host_| that the authenticating client has been rejected. - void RejectAuthenticatingClient() { - host_->RejectAuthenticatingClient(); - } - // Notify |host_| that a client session has closed. void NotifyClientSessionClosed(int connection_index) { get_client(connection_index)->OnConnectionClosed( @@ -468,21 +463,6 @@ message_loop_.Run(); } -TEST_F(ChromotingHostTest, RejectAuthenticatingClient) { - Expectation start = ExpectHostAndSessionManagerStart(); - EXPECT_CALL(host_status_observer_, OnClientAuthenticated(session_jid1_)) - .WillOnce(InvokeWithoutArgs( - this, &ChromotingHostTest::RejectAuthenticatingClient)); - ExpectClientDisconnected( - 0, true, start, - InvokeWithoutArgs(this, &ChromotingHostTest::ShutdownHost)); - EXPECT_CALL(host_status_observer_, OnShutdown()); - - host_->Start(xmpp_login_); - SimulateClientConnection(0, true, true); - message_loop_.Run(); -} - TEST_F(ChromotingHostTest, AuthenticationFailed) { ExpectHostAndSessionManagerStart(); EXPECT_CALL(host_status_observer_, OnAccessDenied(session_jid1_))
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index 17f49b4..d12a5ed2b 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -26,7 +26,6 @@ #include "remoting/host/mouse_shape_pump.h" #include "remoting/host/screen_controls.h" #include "remoting/host/screen_resolution.h" -#include "remoting/host/video_frame_pump.h" #include "remoting/proto/control.pb.h" #include "remoting/proto/event.pb.h" #include "remoting/protocol/client_stub.h" @@ -34,6 +33,7 @@ #include "remoting/protocol/pairing_registry.h" #include "remoting/protocol/session.h" #include "remoting/protocol/session_config.h" +#include "remoting/protocol/video_frame_pump.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h" @@ -296,11 +296,8 @@ protocol::MAX_SESSION_LENGTH)); } - // Disconnect the session if the connection was rejected by the host. - if (!event_handler_->OnSessionAuthenticated(this)) { - DisconnectSession(protocol::SESSION_REJECTED); - return; - } + // Notify EventHandler. + event_handler_->OnSessionAuthenticated(this); // Create the desktop environment. Drop the connection if it could not be // created for any reason (for instance the curtain could not initialize). @@ -487,9 +484,9 @@ // When using IpcDesktopCapturer the capture thread is not useful. scoped_ptr<DesktopCapturerProxy> capturer_proxy(new DesktopCapturerProxy( video_capture_task_runner_, video_capturer.Pass())); - video_frame_pump_.reset( - new VideoFramePump(video_encode_task_runner_, capturer_proxy.Pass(), - video_encoder.Pass(), &mouse_clamping_filter_)); + video_frame_pump_.reset(new protocol::VideoFramePump( + video_encode_task_runner_, capturer_proxy.Pass(), video_encoder.Pass(), + &mouse_clamping_filter_)); // Apply video-control parameters to the new scheduler. video_frame_pump_->SetLosslessEncode(lossless_video_encode_);
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h index 348552d..aa4efc537 100644 --- a/remoting/host/client_session.h +++ b/remoting/host/client_session.h
@@ -41,7 +41,10 @@ class InputInjector; class MouseShapePump; class ScreenControls; + +namespace protocol { class VideoFramePump; +} // namespace protocol // A ClientSession keeps a reference to a connection to a client, and maintains // per-client state. @@ -57,9 +60,8 @@ // Called after authentication has started. virtual void OnSessionAuthenticating(ClientSession* client) = 0; - // Called after authentication has finished successfully. Returns true if - // the connection is allowed, or false otherwise. - virtual bool OnSessionAuthenticated(ClientSession* client) = 0; + // Called after authentication has finished successfully. + virtual void OnSessionAuthenticated(ClientSession* client) = 0; // Called after we've finished connecting all channels. virtual void OnSessionChannelsConnected(ClientSession* client) = 0; @@ -209,7 +211,7 @@ // |video_frame_pump_| and |mouse_shape_pump_| may be nullptr if the video // stream is handled by an extension, see ResetVideoPipeline(). scoped_ptr<AudioPump> audio_pump_; - scoped_ptr<VideoFramePump> video_frame_pump_; + scoped_ptr<protocol::VideoFramePump> video_frame_pump_; scoped_ptr<MouseShapePump> mouse_shape_pump_; // The set of all capabilities supported by the client.
diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc index 780c24f..5e728ff 100644 --- a/remoting/host/client_session_unittest.cc +++ b/remoting/host/client_session_unittest.cc
@@ -16,12 +16,12 @@ #include "remoting/host/audio_capturer.h" #include "remoting/host/client_session.h" #include "remoting/host/desktop_environment.h" -#include "remoting/host/fake_desktop_capturer.h" #include "remoting/host/fake_host_extension.h" #include "remoting/host/fake_mouse_cursor_monitor.h" #include "remoting/host/host_extension.h" #include "remoting/host/host_extension_session.h" #include "remoting/host/host_mock_objects.h" +#include "remoting/protocol/fake_desktop_capturer.h" #include "remoting/protocol/protocol_mock_objects.h" #include "remoting/protocol/test_event_matchers.h" #include "testing/gmock/include/gmock/gmock-matchers.h" @@ -296,7 +296,7 @@ } webrtc::DesktopCapturer* ClientSessionTest::CreateVideoCapturer() { - return new FakeDesktopCapturer(); + return new protocol::FakeDesktopCapturer(); } webrtc::MouseCursorMonitor* ClientSessionTest::CreateMouseCursorMonitor() { @@ -330,8 +330,7 @@ message.set_data("data"); Expectation authenticated = - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) .After(authenticated) .WillOnce(DoAll( @@ -343,8 +342,7 @@ TEST_F(ClientSessionTest, ClipboardStubFilter) { CreateClientSession(); - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(*input_injector_, StartPtr(_)); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)); @@ -449,8 +447,7 @@ mouse_event3.set_y(301); Expectation authenticated = - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(*input_injector_, StartPtr(_)) .After(authenticated); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) @@ -506,8 +503,7 @@ mousedown.set_button_down(true); Expectation authenticated = - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) .After(authenticated); @@ -547,8 +543,7 @@ CreateClientSession(); Expectation authenticated = - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) .After(authenticated); @@ -557,9 +552,9 @@ Expectation connected = authenticated; int input_x[3] = { -999, 100, 999 }; - int expected_x[3] = { 0, 100, FakeDesktopCapturer::kWidth - 1 }; + int expected_x[3] = { 0, 100, protocol::FakeDesktopCapturer::kWidth - 1 }; int input_y[3] = { -999, 50, 999 }; - int expected_y[3] = { 0, 50, FakeDesktopCapturer::kHeight - 1 }; + int expected_y[3] = { 0, 50, protocol::FakeDesktopCapturer::kHeight - 1 }; protocol::MouseEvent expected_event; for (int j = 0; j < 3; j++) { @@ -609,8 +604,7 @@ message.set_data("test"); Expectation authenticated = - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) .After(authenticated) @@ -634,8 +628,7 @@ message.set_data("test"); Expectation authenticated = - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(*input_injector_, StartPtr(_)).After(authenticated); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)) .After(authenticated) @@ -655,8 +648,7 @@ TEST_F(ClientSessionTest, ResetVideoPipeline) { CreateClientSession(); - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _)) .WillOnce(DoAll( @@ -687,8 +679,7 @@ CreateClientSession(); Expectation authenticated = - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); // Verify that the ClientSession reports the correct capabilities, and mimic // the client reporting an overlapping set of capabilities. @@ -743,8 +734,7 @@ SetMatchCapabilitiesExpectation(); - EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)) - .WillOnce(Return(true)); + EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); ConnectClientSession();
diff --git a/remoting/host/desktop_process_unittest.cc b/remoting/host/desktop_process_unittest.cc index a10ffcdd..0886c4c 100644 --- a/remoting/host/desktop_process_unittest.cc +++ b/remoting/host/desktop_process_unittest.cc
@@ -19,10 +19,10 @@ #include "remoting/base/auto_thread_task_runner.h" #include "remoting/host/chromoting_messages.h" #include "remoting/host/desktop_process.h" -#include "remoting/host/fake_desktop_capturer.h" #include "remoting/host/host_exit_codes.h" #include "remoting/host/host_mock_objects.h" #include "remoting/host/screen_resolution.h" +#include "remoting/protocol/fake_desktop_capturer.h" #include "remoting/protocol/protocol_mock_objects.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock_mutant.h" @@ -218,7 +218,7 @@ } webrtc::DesktopCapturer* DesktopProcessTest::CreateVideoCapturer() { - return new FakeDesktopCapturer(); + return new protocol::FakeDesktopCapturer(); } void DesktopProcessTest::DisconnectChannels() {
diff --git a/remoting/host/fake_desktop_environment.cc b/remoting/host/fake_desktop_environment.cc index bff6323..4e887d9c 100644 --- a/remoting/host/fake_desktop_environment.cc +++ b/remoting/host/fake_desktop_environment.cc
@@ -5,9 +5,9 @@ #include "remoting/host/fake_desktop_environment.h" #include "remoting/host/audio_capturer.h" -#include "remoting/host/fake_desktop_capturer.h" #include "remoting/host/gnubby_auth_handler.h" #include "remoting/host/input_injector.h" +#include "remoting/protocol/fake_desktop_capturer.h" namespace remoting { @@ -60,7 +60,8 @@ scoped_ptr<webrtc::DesktopCapturer> FakeDesktopEnvironment::CreateVideoCapturer() { - scoped_ptr<FakeDesktopCapturer> result(new FakeDesktopCapturer()); + scoped_ptr<protocol::FakeDesktopCapturer> result( + new protocol::FakeDesktopCapturer()); if (!frame_generator_.is_null()) result->set_frame_generator(frame_generator_); return result.Pass();
diff --git a/remoting/host/fake_desktop_environment.h b/remoting/host/fake_desktop_environment.h index 061a2d33..c144d0e 100644 --- a/remoting/host/fake_desktop_environment.h +++ b/remoting/host/fake_desktop_environment.h
@@ -6,10 +6,10 @@ #define REMOTING_HOST_FAKE_DESKTOP_ENVIRONMENT_H_ #include "remoting/host/desktop_environment.h" -#include "remoting/host/fake_desktop_capturer.h" #include "remoting/host/fake_mouse_cursor_monitor.h" #include "remoting/host/input_injector.h" #include "remoting/host/screen_controls.h" +#include "remoting/protocol/fake_desktop_capturer.h" namespace remoting { @@ -40,10 +40,10 @@ FakeDesktopEnvironment(); ~FakeDesktopEnvironment() override; - // Sets frame generator to be used for FakeDesktopCapturer created by - // FakeDesktopEnvironment. + // Sets frame generator to be used for protocol::FakeDesktopCapturer created + // by FakeDesktopEnvironment. void set_frame_generator( - FakeDesktopCapturer::FrameGenerator frame_generator) { + protocol::FakeDesktopCapturer::FrameGenerator frame_generator) { frame_generator_ = frame_generator; } @@ -59,7 +59,7 @@ protocol::ClientStub* client_stub) override; private: - FakeDesktopCapturer::FrameGenerator frame_generator_; + protocol::FakeDesktopCapturer::FrameGenerator frame_generator_; DISALLOW_COPY_AND_ASSIGN(FakeDesktopEnvironment); }; @@ -69,10 +69,10 @@ FakeDesktopEnvironmentFactory(); ~FakeDesktopEnvironmentFactory() override; - // Sets frame generator to be used for FakeDesktopCapturer created by - // FakeDesktopEnvironment. + // Sets frame generator to be used for protocol::FakeDesktopCapturer created + // by FakeDesktopEnvironment. void set_frame_generator( - FakeDesktopCapturer::FrameGenerator frame_generator) { + protocol::FakeDesktopCapturer::FrameGenerator frame_generator) { frame_generator_ = frame_generator; } @@ -84,7 +84,7 @@ void SetEnableGnubbyAuth(bool enable) override; private: - FakeDesktopCapturer::FrameGenerator frame_generator_; + protocol::FakeDesktopCapturer::FrameGenerator frame_generator_; DISALLOW_COPY_AND_ASSIGN(FakeDesktopEnvironmentFactory); };
diff --git a/remoting/host/host_mock_objects.cc b/remoting/host/host_mock_objects.cc index 7b4d28b..91e7f87 100644 --- a/remoting/host/host_mock_objects.cc +++ b/remoting/host/host_mock_objects.cc
@@ -89,15 +89,4 @@ MockMouseCursorMonitor::~MockMouseCursorMonitor() {} -MockVideoEncoder::MockVideoEncoder() { -} - -MockVideoEncoder::~MockVideoEncoder() { -} - -scoped_ptr<VideoPacket> MockVideoEncoder::Encode( - const webrtc::DesktopFrame& frame) { - return make_scoped_ptr(EncodePtr(frame)); -} - } // namespace remoting
diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h index eaae574..fbdef779 100644 --- a/remoting/host/host_mock_objects.h +++ b/remoting/host/host_mock_objects.h
@@ -76,7 +76,7 @@ ~MockClientSessionEventHandler() override; MOCK_METHOD1(OnSessionAuthenticating, void(ClientSession* client)); - MOCK_METHOD1(OnSessionAuthenticated, bool(ClientSession* client)); + MOCK_METHOD1(OnSessionAuthenticated, void(ClientSession* client)); MOCK_METHOD1(OnSessionChannelsConnected, void(ClientSession* client)); MOCK_METHOD1(OnSessionAuthenticationFailed, void(ClientSession* client)); MOCK_METHOD1(OnSessionClosed, void(ClientSession* client)); @@ -166,18 +166,6 @@ DISALLOW_COPY_AND_ASSIGN(MockMouseCursorMonitor); }; -class MockVideoEncoder : public VideoEncoder { - public: - MockVideoEncoder(); - ~MockVideoEncoder() override; - - MOCK_METHOD1(SetLosslessEncode, void(bool)); - MOCK_METHOD1(SetLosslessColor, void(bool)); - MOCK_METHOD1(EncodePtr, VideoPacket*(const webrtc::DesktopFrame&)); - - scoped_ptr<VideoPacket> Encode(const webrtc::DesktopFrame& frame) override; -}; - } // namespace remoting #endif // REMOTING_HOST_HOST_MOCK_OBJECTS_H_
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc index 1de0f29..508382de 100644 --- a/remoting/host/ipc_desktop_environment_unittest.cc +++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -24,10 +24,10 @@ #include "remoting/host/desktop_session.h" #include "remoting/host/desktop_session_connector.h" #include "remoting/host/desktop_session_proxy.h" -#include "remoting/host/fake_desktop_capturer.h" #include "remoting/host/fake_mouse_cursor_monitor.h" #include "remoting/host/host_mock_objects.h" #include "remoting/host/ipc_desktop_environment.h" +#include "remoting/protocol/fake_desktop_capturer.h" #include "remoting/protocol/protocol_mock_objects.h" #include "remoting/protocol/test_event_matchers.h" #include "testing/gmock/include/gmock/gmock.h" @@ -366,7 +366,7 @@ } webrtc::DesktopCapturer* IpcDesktopEnvironmentTest::CreateVideoCapturer() { - return new FakeDesktopCapturer(); + return new protocol::FakeDesktopCapturer(); } webrtc::MouseCursorMonitor*
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index 725de14..ed1ce1c 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc
@@ -82,43 +82,33 @@ } void It2MeHost::Disconnect() { - if (!host_context_->network_task_runner()->BelongsToCurrentThread()) { - DCHECK(task_runner_->BelongsToCurrentThread()); - host_context_->network_task_runner()->PostTask( - FROM_HERE, base::Bind(&It2MeHost::Disconnect, this)); - return; + DCHECK(task_runner_->BelongsToCurrentThread()); + host_context_->network_task_runner()->PostTask( + FROM_HERE, base::Bind(&It2MeHost::Shutdown, this)); +} + +void It2MeHost::Shutdown() { + DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); + + confirmation_dialog_proxy_.reset(); + + host_event_logger_.reset(); + if (host_) { + host_->RemoveStatusObserver(this); + host_.reset(); } - switch (state_) { - case kDisconnected: - ShutdownOnNetworkThread(); - return; + register_request_.reset(); + host_status_logger_.reset(); + signal_strategy_.reset(); - case kStarting: - SetState(kDisconnecting, ""); - SetState(kDisconnected, ""); - ShutdownOnNetworkThread(); - return; + // Post tasks to delete UI objects on the UI thread. + host_context_->ui_task_runner()->DeleteSoon( + FROM_HERE, desktop_environment_factory_.release()); + host_context_->ui_task_runner()->DeleteSoon(FROM_HERE, + policy_watcher_.release()); - case kDisconnecting: - return; - - default: - SetState(kDisconnecting, ""); - - if (!host_) { - SetState(kDisconnected, ""); - ShutdownOnNetworkThread(); - return; - } - - // Deleting the host destroys SignalStrategy synchronously, but - // SignalStrategy::Listener handlers are not allowed to destroy - // SignalStrategy, so post task to destroy the host later. - host_context_->network_task_runner()->PostTask( - FROM_HERE, base::Bind(&It2MeHost::ShutdownOnNetworkThread, this)); - return; - } + SetState(kDisconnected, ""); } void It2MeHost::RequestNatPolicy() { @@ -162,7 +152,7 @@ break; case It2MeConfirmationDialog::Result::CANCEL: - Disconnect(); + Shutdown(); break; default: @@ -272,61 +262,21 @@ return; } -void It2MeHost::ShutdownOnNetworkThread() { - DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); - DCHECK(state_ == kDisconnecting || state_ == kDisconnected); - - confirmation_dialog_proxy_.reset(); - - if (state_ == kDisconnecting) { - host_event_logger_.reset(); - host_->RemoveStatusObserver(this); - host_.reset(); - - register_request_.reset(); - host_status_logger_.reset(); - signal_strategy_.reset(); - SetState(kDisconnected, ""); - } - - host_context_->ui_task_runner()->PostTask( - FROM_HERE, base::Bind(&It2MeHost::ShutdownOnUiThread, this)); -} - -void It2MeHost::ShutdownOnUiThread() { - DCHECK(host_context_->ui_task_runner()->BelongsToCurrentThread()); - - // Destroy the DesktopEnvironmentFactory, to free thread references. - desktop_environment_factory_.reset(); - - // Stop listening for policy updates. - policy_watcher_.reset(); -} - void It2MeHost::OnAccessDenied(const std::string& jid) { DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); ++failed_login_attempts_; if (failed_login_attempts_ == kMaxLoginAttempts) { - Disconnect(); + Shutdown(); } } -void It2MeHost::OnClientAuthenticated(const std::string& jid) { +void It2MeHost::OnClientConnected(const std::string& jid) { DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); - if (state_ == kDisconnecting) { - // Ignore the new connection if we are disconnecting. - return; - } - if (state_ == kConnected) { - // If we already connected another client then one of the connections may be - // an attacker, so both are suspect and we have to reject the second - // connection and shutdown the host. - host_->RejectAuthenticatingClient(); - Disconnect(); - return; - } + // ChromotingHost doesn't allow multiple concurrent connection and the + // host is destroyed in OnClientDisconnected() after the first connection. + CHECK_NE(state_, kConnected); std::string client_username = jid; size_t pos = client_username.find('/'); @@ -346,7 +296,7 @@ void It2MeHost::OnClientDisconnected(const std::string& jid) { DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); - Disconnect(); + Shutdown(); } void It2MeHost::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) { @@ -388,7 +338,7 @@ // When transitioning from enabled to disabled, force disconnect any // existing session. if (nat_traversal_enabled_ && !nat_traversal_enabled && IsConnected()) { - Disconnect(); + Shutdown(); } nat_traversal_enabled_ = nat_traversal_enabled; @@ -406,7 +356,7 @@ // When setting a host domain policy, force disconnect any existing session. if (!host_domain.empty() && IsConnected()) { - Disconnect(); + Shutdown(); } required_host_domain_ = host_domain; @@ -429,33 +379,29 @@ break; case kStarting: DCHECK(state == kRequestedAccessCode || - state == kDisconnecting || + state == kDisconnected || state == kError || state == kInvalidDomainError) << state; break; case kRequestedAccessCode: DCHECK(state == kReceivedAccessCode || - state == kDisconnecting || + state == kDisconnected || state == kError) << state; break; case kReceivedAccessCode: DCHECK(state == kConnected || - state == kDisconnecting || - state == kError) << state; - break; - case kConnected: - DCHECK(state == kDisconnecting || state == kDisconnected || state == kError) << state; break; - case kDisconnecting: - DCHECK(state == kDisconnected) << state; + case kConnected: + DCHECK(state == kDisconnected || + state == kError) << state; break; case kError: - DCHECK(state == kDisconnecting) << state; + DCHECK(state == kDisconnected) << state; break; case kInvalidDomainError: - DCHECK(state == kDisconnecting) << state; + DCHECK(state == kDisconnected) << state; break; }; @@ -480,7 +426,7 @@ if (!error_message.empty()) { SetState(kError, error_message); - Disconnect(); + Shutdown(); return; } @@ -492,7 +438,7 @@ std::string error_message = "Failed to generate host certificate."; LOG(ERROR) << error_message; SetState(kError, error_message); - Disconnect(); + Shutdown(); return; }
diff --git a/remoting/host/it2me/it2me_host.h b/remoting/host/it2me/it2me_host.h index 0b16085..0619dd6 100644 --- a/remoting/host/it2me/it2me_host.h +++ b/remoting/host/it2me/it2me_host.h
@@ -42,7 +42,6 @@ kRequestedAccessCode, kReceivedAccessCode, kConnected, - kDisconnecting, kError, kInvalidDomainError }; @@ -74,8 +73,7 @@ // Creates It2Me host structures and starts the host. virtual void Connect(); - // Disconnects the host, ready for tear-down. - // Also called internally, from the network thread. + // Disconnects and shuts down the host. virtual void Disconnect(); // TODO (weitaosu): Remove RequestNatPolicy from It2MeHost. @@ -84,7 +82,7 @@ // remoting::HostStatusObserver implementation. void OnAccessDenied(const std::string& jid) override; - void OnClientAuthenticated(const std::string& jid) override; + void OnClientConnected(const std::string& jid) override; void OnClientDisconnected(const std::string& jid) override; void SetStateForTesting(It2MeHostState state, @@ -128,14 +126,6 @@ const base::TimeDelta& lifetime, const std::string& error_message); - // Shuts down |host_| on the network thread and posts ShutdownOnUiThread() - // to shut down UI thread resources. - void ShutdownOnNetworkThread(); - - // Shuts down |desktop_environment_factory_| and |policy_watcher_| on - // the UI thread. - void ShutdownOnUiThread(); - // Called when initial policies are read, and when they change. void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies); @@ -146,6 +136,8 @@ void UpdateNatPolicy(bool nat_traversal_enabled); void UpdateHostDomainPolicy(const std::string& host_domain); + void Shutdown(); + // Caller supplied fields. scoped_ptr<ChromotingHostContext> host_context_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/remoting/host/it2me/it2me_native_messaging_host.cc b/remoting/host/it2me/it2me_native_messaging_host.cc index aedb4c8..6e8fe17 100644 --- a/remoting/host/it2me/it2me_native_messaging_host.cc +++ b/remoting/host/it2me/it2me_native_messaging_host.cc
@@ -33,7 +33,6 @@ {kRequestedAccessCode, "REQUESTED_ACCESS_CODE"}, {kReceivedAccessCode, "RECEIVED_ACCESS_CODE"}, {kConnected, "CONNECTED"}, - {kDisconnecting, "DISCONNECTING"}, {kError, "ERROR"}, {kInvalidDomainError, "INVALID_DOMAIN_ERROR"}, }; @@ -255,8 +254,7 @@ scoped_ptr<base::DictionaryValue> message(new base::DictionaryValue()); message->SetString("type", "hostStateChanged"); - message->SetString("state", - It2MeNativeMessagingHost::HostStateToString(state)); + message->SetString("state", HostStateToString(state)); switch (state_) { case kReceivedAccessCode:
diff --git a/remoting/host/it2me/it2me_native_messaging_host_main.cc b/remoting/host/it2me/it2me_native_messaging_host_main.cc index bc89211..e0f9349 100644 --- a/remoting/host/it2me/it2me_native_messaging_host_main.cc +++ b/remoting/host/it2me/it2me_native_messaging_host_main.cc
@@ -23,6 +23,8 @@ #if defined(OS_LINUX) #include <gtk/gtk.h> #include <X11/Xlib.h> + +#include "base/linux_util.h" #endif // defined(OS_LINUX) #if defined(OS_MACOSX) @@ -73,6 +75,10 @@ // Continue windows. Calling with nullptr arguments because we don't have // any command line arguments for gtk to consume. gtk_init(nullptr, nullptr); + + // Need to prime the host OS version value for linux to prevent IO on the + // network thread. base::GetLinuxDistro() caches the result. + base::GetLinuxDistro(); #endif // OS_LINUX // Enable support for SSL server sockets, which must be done while still
diff --git a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc index 94861e4..c36bd61 100644 --- a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc +++ b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
@@ -134,7 +134,6 @@ return; } - RunSetState(kDisconnecting); RunSetState(kDisconnected); } @@ -379,11 +378,10 @@ void It2MeNativeMessagingHostTest::VerifyDisconnectResponses(int request_id) { bool disconnect_response_received = false; - bool disconnecting_received = false; bool disconnected_received = false; - // We expect a total of 3 messages: 1 connectResponse and 2 hostStateChanged. - for (int i = 0; i < 3; ++i) { + // We expect a total of 3 messages: 1 connectResponse and 1 hostStateChanged. + for (int i = 0; i < 2; ++i) { scoped_ptr<base::DictionaryValue> response = ReadMessageFromOutputPipe(); ASSERT_TRUE(response); @@ -397,12 +395,7 @@ } else if (type == "hostStateChanged") { std::string state; ASSERT_TRUE(response->GetString("state", &state)); - if (state == - It2MeNativeMessagingHost::HostStateToString(kDisconnecting)) { - EXPECT_FALSE(disconnecting_received); - disconnecting_received = true; - } else if (state == - It2MeNativeMessagingHost::HostStateToString(kDisconnected)) { + if (state == It2MeNativeMessagingHost::HostStateToString(kDisconnected)) { EXPECT_FALSE(disconnected_received); disconnected_received = true; } else {
diff --git a/remoting/host/shaped_desktop_capturer_unittest.cc b/remoting/host/shaped_desktop_capturer_unittest.cc index 371c473..d3a04d75 100644 --- a/remoting/host/shaped_desktop_capturer_unittest.cc +++ b/remoting/host/shaped_desktop_capturer_unittest.cc
@@ -5,7 +5,7 @@ #include "remoting/host/shaped_desktop_capturer.h" #include "remoting/host/desktop_shape_tracker.h" -#include "remoting/host/fake_desktop_capturer.h" +#include "remoting/protocol/fake_desktop_capturer.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" @@ -55,7 +55,7 @@ // Verify that captured frame have shape. TEST_F(ShapedDesktopCapturerTest, Basic) { ShapedDesktopCapturer capturer( - make_scoped_ptr(new FakeDesktopCapturer()), + make_scoped_ptr(new protocol::FakeDesktopCapturer()), make_scoped_ptr(new FakeDesktopShapeTracker())); capturer.Start(this); capturer.Capture(webrtc::DesktopRegion());
diff --git a/remoting/protocol/BUILD.gn b/remoting/protocol/BUILD.gn index 20c1e64..593580d 100644 --- a/remoting/protocol/BUILD.gn +++ b/remoting/protocol/BUILD.gn
@@ -30,24 +30,23 @@ "//remoting/signaling", ] - if (is_nacl) { - sources -= [ - "chromium_port_allocator.cc", - "chromium_port_allocator_factory.cc", - "chromium_socket_factory.cc", - ] - } + if (!is_nacl) { + sources += + rebase_path(remoting_srcs_gypi_values.remoting_protocol_nonnacl_sources, + ".", + "//remoting") - if (!is_nacl && 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", - ] - } else { - sources -= [ "webrtc_transport.cc" ] + 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", + ] + } else { + sources -= [ "webrtc_transport.cc" ] + } } } @@ -61,6 +60,8 @@ "fake_connection_to_host.h", "fake_datagram_socket.cc", "fake_datagram_socket.h", + "fake_desktop_capturer.cc", + "fake_desktop_capturer.h", "fake_session.cc", "fake_session.h", "fake_stream_socket.cc", @@ -81,6 +82,7 @@ sources = [ "authenticator_test_base.cc", "authenticator_test_base.h", + "capture_scheduler_unittest.cc", "channel_multiplexer_unittest.cc", "channel_socket_adapter_unittest.cc", "chromium_socket_factory_unittest.cc", @@ -108,6 +110,7 @@ "ssl_hmac_channel_authenticator_unittest.cc", "third_party_authenticator_unittest.cc", "v2_authenticator_unittest.cc", + "video_frame_pump_unittest.cc", "webrtc_transport_unittest.cc", ]
diff --git a/remoting/host/capture_scheduler.cc b/remoting/protocol/capture_scheduler.cc similarity index 96% rename from remoting/host/capture_scheduler.cc rename to remoting/protocol/capture_scheduler.cc index 556c2076..1e8f73a1 100644 --- a/remoting/host/capture_scheduler.cc +++ b/remoting/protocol/capture_scheduler.cc
@@ -1,8 +1,8 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "remoting/host/capture_scheduler.h" +#include "remoting/protocol/capture_scheduler.h" #include <algorithm> @@ -39,6 +39,7 @@ } // namespace namespace remoting { +namespace protocol { // We assume that the number of available cores is constant. CaptureScheduler::CaptureScheduler(const base::Closure& capture_closure) @@ -178,4 +179,5 @@ capture_closure_.Run(); } +} // namespace protocol } // namespace remoting
diff --git a/remoting/host/capture_scheduler.h b/remoting/protocol/capture_scheduler.h similarity index 90% rename from remoting/host/capture_scheduler.h rename to remoting/protocol/capture_scheduler.h index be8131b..0b01c63 100644 --- a/remoting/host/capture_scheduler.h +++ b/remoting/protocol/capture_scheduler.h
@@ -1,11 +1,12 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef REMOTING_HOST_CAPTURE_SCHEDULER_H_ -#define REMOTING_HOST_CAPTURE_SCHEDULER_H_ +#ifndef REMOTING_PROTOCOL_CAPTURE_SCHEDULER_H_ +#define REMOTING_PROTOCOL_CAPTURE_SCHEDULER_H_ #include "base/callback.h" +#include "base/macros.h" #include "base/threading/thread_checker.h" #include "base/time/tick_clock.h" #include "base/time/time.h" @@ -17,6 +18,8 @@ class VideoPacket; +namespace protocol { + // CaptureScheduler is used by the VideoFramePump to schedule frame capturer, // taking into account capture delay, encoder delay, network bandwidth, etc. // It implements VideoFeedbackStub to receive frame acknowledgments from the @@ -27,7 +30,7 @@ // - Parallelize capture, encode and transmission, to achieve frame rate as // close to the target of 30fps as possible. // - Limit CPU usage to 50%. -class CaptureScheduler : public protocol::VideoFeedbackStub { +class CaptureScheduler : public VideoFeedbackStub { public: explicit CaptureScheduler(const base::Closure& capture_closure); ~CaptureScheduler() override; @@ -108,6 +111,7 @@ DISALLOW_COPY_AND_ASSIGN(CaptureScheduler); }; +} // namespace protocol } // namespace remoting -#endif // REMOTING_HOST_CAPTURE_SCHEDULER_H_ +#endif // REMOTING_PROTOCOL_CAPTURE_SCHEDULER_H_
diff --git a/remoting/host/capture_scheduler_unittest.cc b/remoting/protocol/capture_scheduler_unittest.cc similarity index 97% rename from remoting/host/capture_scheduler_unittest.cc rename to remoting/protocol/capture_scheduler_unittest.cc index 7b6982ff..a6dcc875 100644 --- a/remoting/host/capture_scheduler_unittest.cc +++ b/remoting/protocol/capture_scheduler_unittest.cc
@@ -1,8 +1,8 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "remoting/host/capture_scheduler.h" +#include "remoting/protocol/capture_scheduler.h" #include "base/message_loop/message_loop.h" #include "base/test/simple_test_tick_clock.h" @@ -11,6 +11,7 @@ #include "testing/gtest/include/gtest/gtest.h" namespace remoting { +namespace protocol { static const int kTestInputs[] = { 100, 50, 30, 20, 10, 30, 60, 80 }; static const int kMinumumFrameIntervalMs = 50; @@ -192,4 +193,5 @@ EXPECT_TRUE(capture_timer_->IsRunning()); } +} // namespace protocol } // namespace remoting
diff --git a/remoting/host/fake_desktop_capturer.cc b/remoting/protocol/fake_desktop_capturer.cc similarity index 96% rename from remoting/host/fake_desktop_capturer.cc rename to remoting/protocol/fake_desktop_capturer.cc index 520d396..bfa34f1 100644 --- a/remoting/host/fake_desktop_capturer.cc +++ b/remoting/protocol/fake_desktop_capturer.cc
@@ -1,16 +1,16 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "remoting/host/fake_desktop_capturer.h" +#include "remoting/protocol/fake_desktop_capturer.h" #include "base/bind.h" #include "base/logging.h" -#include "base/memory/ref_counted.h" #include "base/time/time.h" #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" namespace remoting { +namespace protocol { // FakeDesktopCapturer generates a white picture of size kWidth x kHeight // with a rectangle of size kBoxWidth x kBoxHeight. The rectangle moves kSpeed @@ -150,4 +150,5 @@ callback_->OnCaptureCompleted(frame.release()); } +} // namespace protocol } // namespace remoting
diff --git a/remoting/host/fake_desktop_capturer.h b/remoting/protocol/fake_desktop_capturer.h similarity index 83% rename from remoting/host/fake_desktop_capturer.h rename to remoting/protocol/fake_desktop_capturer.h index 11a0150..ab75aba 100644 --- a/remoting/host/fake_desktop_capturer.h +++ b/remoting/protocol/fake_desktop_capturer.h
@@ -1,17 +1,19 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef REMOTING_HOST_FAKE_DESKTOP_CAPTURER_H_ -#define REMOTING_HOST_FAKE_DESKTOP_CAPTURER_H_ +#ifndef REMOTING_PROTOCOL_FAKE_DESKTOP_CAPTURER_H_ +#define REMOTING_PROTOCOL_FAKE_DESKTOP_CAPTURER_H_ #include "base/callback.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" #include "third_party/webrtc/modules/desktop_capture/screen_capture_frame_queue.h" namespace remoting { +namespace protocol { // A FakeDesktopCapturer generates artificial image for testing purpose. // @@ -44,6 +46,7 @@ DISALLOW_COPY_AND_ASSIGN(FakeDesktopCapturer); }; +} // namespace protocol } // namespace remoting -#endif // REMOTING_HOST_FAKE_DESKTOP_CAPTURER_H_ +#endif // REMOTING_PROTOCOL_FAKE_DESKTOP_CAPTURER_H_
diff --git a/remoting/host/video_frame_pump.cc b/remoting/protocol/video_frame_pump.cc similarity index 98% rename from remoting/host/video_frame_pump.cc rename to remoting/protocol/video_frame_pump.cc index 9c82efe..8e286de 100644 --- a/remoting/host/video_frame_pump.cc +++ b/remoting/protocol/video_frame_pump.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 "remoting/host/video_frame_pump.h" +#include "remoting/protocol/video_frame_pump.h" #include <algorithm> @@ -19,6 +19,7 @@ #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" namespace remoting { +namespace protocol { // Interval between empty keep-alive frames. These frames are sent only when the // stream is paused or inactive for some other reason (e.g. when blocked on @@ -253,4 +254,5 @@ keep_alive_timer_.Reset(); } +} // namespace protocol } // namespace remoting
diff --git a/remoting/host/video_frame_pump.h b/remoting/protocol/video_frame_pump.h similarity index 96% rename from remoting/host/video_frame_pump.h rename to remoting/protocol/video_frame_pump.h index f4542caf..1974ec6 100644 --- a/remoting/host/video_frame_pump.h +++ b/remoting/protocol/video_frame_pump.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 REMOTING_HOST_VIDEO_FRAME_PUMP_H_ -#define REMOTING_HOST_VIDEO_FRAME_PUMP_H_ +#ifndef REMOTING_PROTOCOL_VIDEO_FRAME_PUMP_H_ +#define REMOTING_PROTOCOL_VIDEO_FRAME_PUMP_H_ #include "base/basictypes.h" #include "base/memory/ref_counted.h" @@ -13,8 +13,8 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "remoting/codec/video_encoder.h" -#include "remoting/host/capture_scheduler.h" #include "remoting/proto/video.pb.h" +#include "remoting/protocol/capture_scheduler.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" namespace base { @@ -22,11 +22,10 @@ } // namespace base namespace remoting { - namespace protocol { + class VideoFeedbackStub; class VideoStub; -} // namespace protocol // Class responsible for scheduling frame captures from a screen capturer., // delivering them to a VideoEncoder to encode, and @@ -192,6 +191,7 @@ DISALLOW_COPY_AND_ASSIGN(VideoFramePump); }; +} // namespace protocol } // namespace remoting -#endif // REMOTING_HOST_VIDEO_FRAME_PUMP_H_ +#endif // REMOTING_PROTOCOL_VIDEO_FRAME_PUMP_H_
diff --git a/remoting/host/video_frame_pump_unittest.cc b/remoting/protocol/video_frame_pump_unittest.cc similarity index 84% rename from remoting/host/video_frame_pump_unittest.cc rename to remoting/protocol/video_frame_pump_unittest.cc index d6490f4..01aedb3 100644 --- a/remoting/host/video_frame_pump_unittest.cc +++ b/remoting/protocol/video_frame_pump_unittest.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 "remoting/host/video_frame_pump.h" +#include "remoting/protocol/video_frame_pump.h" #include "base/bind.h" #include "base/message_loop/message_loop.h" @@ -12,19 +12,15 @@ #include "remoting/base/auto_thread_task_runner.h" #include "remoting/codec/video_encoder.h" #include "remoting/codec/video_encoder_verbatim.h" -#include "remoting/host/desktop_capturer_proxy.h" -#include "remoting/host/fake_desktop_capturer.h" -#include "remoting/host/host_mock_objects.h" #include "remoting/proto/control.pb.h" #include "remoting/proto/video.pb.h" +#include "remoting/protocol/fake_desktop_capturer.h" #include "remoting/protocol/protocol_mock_objects.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" #include "third_party/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h" -using ::remoting::protocol::MockVideoStub; - using ::testing::_; using ::testing::AtLeast; using ::testing::DoAll; @@ -33,6 +29,7 @@ using ::testing::Return; namespace remoting { +namespace protocol { namespace { @@ -52,6 +49,20 @@ return make_scoped_ptr(new webrtc::BasicDesktopFrame(kSize)); } +class MockVideoEncoder : public VideoEncoder { + public: + MockVideoEncoder() {} + ~MockVideoEncoder() {} + + MOCK_METHOD1(SetLosslessEncode, void(bool)); + MOCK_METHOD1(SetLosslessColor, void(bool)); + MOCK_METHOD1(EncodePtr, VideoPacket*(const webrtc::DesktopFrame&)); + + scoped_ptr<VideoPacket> Encode(const webrtc::DesktopFrame& frame) { + return make_scoped_ptr(EncodePtr(frame)); + } +}; + } // namespace static const int kWidth = 640; @@ -123,7 +134,6 @@ protected: base::MessageLoop message_loop_; base::RunLoop run_loop_; - scoped_refptr<AutoThreadTaskRunner> capture_task_runner_; scoped_refptr<AutoThreadTaskRunner> encode_task_runner_; scoped_refptr<AutoThreadTaskRunner> main_task_runner_; scoped_ptr<VideoFramePump> pump_; @@ -134,7 +144,6 @@ void VideoFramePumpTest::SetUp() { main_task_runner_ = new AutoThreadTaskRunner( message_loop_.task_runner(), run_loop_.QuitClosure()); - capture_task_runner_ = AutoThread::Create("capture", main_task_runner_); encode_task_runner_ = AutoThread::Create("encode", main_task_runner_); } @@ -142,7 +151,6 @@ pump_.reset(); // Release the task runners, so that the test can quit. - capture_task_runner_ = nullptr; encode_task_runner_ = nullptr; main_task_runner_ = nullptr; @@ -154,7 +162,7 @@ // cycle. TEST_F(VideoFramePumpTest, StartAndStop) { scoped_ptr<ThreadCheckDesktopCapturer> capturer( - new ThreadCheckDesktopCapturer(capture_task_runner_)); + new ThreadCheckDesktopCapturer(main_task_runner_)); scoped_ptr<ThreadCheckVideoEncoder> encoder( new ThreadCheckVideoEncoder(encode_task_runner_)); @@ -162,15 +170,12 @@ // When the first ProcessVideoPacket is received we stop the VideoFramePump. EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _)) - .WillOnce(DoAll( - FinishSend(), - InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit))) + .WillOnce(DoAll(FinishSend(), + InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit))) .RetiresOnSaturation(); // Start video frame capture. - pump_.reset(new VideoFramePump(encode_task_runner_, - make_scoped_ptr(new DesktopCapturerProxy( - capture_task_runner_, capturer.Pass())), + pump_.reset(new VideoFramePump(encode_task_runner_, capturer.Pass(), encoder.Pass(), &video_stub_)); // Run MessageLoop until the first frame is received. @@ -197,9 +202,7 @@ .RetiresOnSaturation(); // Start video frame capture. - pump_.reset(new VideoFramePump(encode_task_runner_, - make_scoped_ptr(new DesktopCapturerProxy( - capture_task_runner_, capturer.Pass())), + pump_.reset(new VideoFramePump(encode_task_runner_, capturer.Pass(), encoder.Pass(), &video_stub_)); // Run MessageLoop until the first frame is received.. @@ -227,13 +230,12 @@ .RetiresOnSaturation(); // Start video frame capture. - pump_.reset(new VideoFramePump(encode_task_runner_, - make_scoped_ptr(new DesktopCapturerProxy( - capture_task_runner_, capturer.Pass())), + pump_.reset(new VideoFramePump(encode_task_runner_, capturer.Pass(), encoder.Pass(), &video_stub_)); - // Run MessageLoop until the first frame is received.. + // Run MessageLoop until the first frame is received. run_loop.Run(); } +} // namespace protocol } // namespace remoting
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 3e58552..93cd084 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp
@@ -244,6 +244,7 @@ ], 'sources': [ '<@(remoting_protocol_sources)', + '<@(remoting_protocol_nonnacl_sources)', '<@(remoting_signaling_sources)', ], 'conditions': [
diff --git a/remoting/remoting_host_srcs.gypi b/remoting/remoting_host_srcs.gypi index 3daadc7..a699670 100644 --- a/remoting/remoting_host_srcs.gypi +++ b/remoting/remoting_host_srcs.gypi
@@ -22,8 +22,6 @@ 'host/basic_desktop_environment.h', 'host/branding.cc', 'host/branding.h', - 'host/capture_scheduler.cc', - 'host/capture_scheduler.h', 'host/chromeos/aura_desktop_capturer.cc', 'host/chromeos/aura_desktop_capturer.h', 'host/chromeos/clipboard_aura.cc', @@ -251,8 +249,6 @@ 'host/usage_stats_consent_win.cc', 'host/username.cc', 'host/username.h', - 'host/video_frame_pump.cc', - 'host/video_frame_pump.h', 'host/video_frame_recorder.cc', 'host/video_frame_recorder.h', 'host/video_frame_recorder_host_extension.cc',
diff --git a/remoting/remoting_nacl.gyp b/remoting/remoting_nacl.gyp index 7ea8e1a..3c5a2848 100644 --- a/remoting/remoting_nacl.gyp +++ b/remoting/remoting_nacl.gyp
@@ -123,9 +123,6 @@ ], 'sources!': [ 'base/url_request_context_getter.cc', - 'protocol/chromium_socket_factory.cc', - 'protocol/chromium_port_allocator_factory.cc', - 'protocol/webrtc_transport.cc', ], # Include normalizing_input_filter_*.cc excluded by the filename
diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi index d3ef9b4..1ba30ee 100644 --- a/remoting/remoting_srcs.gypi +++ b/remoting/remoting_srcs.gypi
@@ -86,12 +86,6 @@ 'protocol/channel_multiplexer.h', 'protocol/channel_socket_adapter.cc', 'protocol/channel_socket_adapter.h', - 'protocol/chromium_port_allocator.cc', - 'protocol/chromium_port_allocator.h', - 'protocol/chromium_port_allocator_factory.cc', - 'protocol/chromium_port_allocator_factory.h', - 'protocol/chromium_socket_factory.cc', - 'protocol/chromium_socket_factory.h', 'protocol/client_control_dispatcher.cc', 'protocol/client_control_dispatcher.h', 'protocol/client_event_dispatcher.cc', @@ -208,6 +202,20 @@ 'protocol/v2_authenticator.cc', 'protocol/v2_authenticator.h', 'protocol/video_stub.h', + ], + + # Files in protocol that don't compile for NaCl. + 'remoting_protocol_nonnacl_sources': [ + 'protocol/capture_scheduler.cc', + 'protocol/capture_scheduler.h', + 'protocol/chromium_port_allocator.cc', + 'protocol/chromium_port_allocator.h', + 'protocol/chromium_port_allocator_factory.cc', + 'protocol/chromium_port_allocator_factory.h', + 'protocol/chromium_socket_factory.cc', + 'protocol/chromium_socket_factory.h', + 'protocol/video_frame_pump.cc', + 'protocol/video_frame_pump.h', 'protocol/webrtc_transport.cc', 'protocol/webrtc_transport.h', ],
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi index 418fbd94..1362cc1 100644 --- a/remoting/remoting_test.gypi +++ b/remoting/remoting_test.gypi
@@ -21,8 +21,6 @@ ], 'sources': [ # Note: sources list duplicated in GN build. - 'host/fake_desktop_capturer.cc', - 'host/fake_desktop_capturer.h', 'host/fake_desktop_environment.cc', 'host/fake_desktop_environment.h', 'host/fake_host_extension.cc', @@ -38,6 +36,8 @@ 'protocol/fake_connection_to_host.h', 'protocol/fake_datagram_socket.cc', 'protocol/fake_datagram_socket.h', + 'protocol/fake_desktop_capturer.cc', + 'protocol/fake_desktop_capturer.h', 'protocol/fake_session.cc', 'protocol/fake_session.h', 'protocol/fake_stream_socket.cc', @@ -245,7 +245,6 @@ 'host/backoff_timer_unittest.cc', 'host/branding.cc', 'host/branding.h', - 'host/capture_scheduler_unittest.cc', 'host/chromeos/aura_desktop_capturer_unittest.cc', 'host/chromeos/clipboard_aura_unittest.cc', 'host/chromoting_host_context_unittest.cc', @@ -295,7 +294,6 @@ 'host/third_party_auth_config_unittest.cc', 'host/token_validator_factory_impl_unittest.cc', 'host/touch_injector_win_unittest.cc', - 'host/video_frame_pump_unittest.cc', 'host/video_frame_recorder_unittest.cc', 'host/win/rdp_client_unittest.cc', 'host/win/worker_process_launcher.cc', @@ -303,6 +301,7 @@ 'host/win/worker_process_launcher_unittest.cc', 'protocol/authenticator_test_base.cc', 'protocol/authenticator_test_base.h', + 'protocol/capture_scheduler_unittest.cc', 'protocol/channel_multiplexer_unittest.cc', 'protocol/channel_socket_adapter_unittest.cc', 'protocol/chromium_socket_factory_unittest.cc', @@ -330,6 +329,7 @@ 'protocol/ssl_hmac_channel_authenticator_unittest.cc', 'protocol/third_party_authenticator_unittest.cc', 'protocol/v2_authenticator_unittest.cc', + 'protocol/video_frame_pump_unittest.cc', 'protocol/webrtc_transport_unittest.cc', 'signaling/iq_sender_unittest.cc', 'signaling/jid_util_unittest.cc',
diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc index bddfb3f94..61294da 100644 --- a/remoting/test/protocol_perftest.cc +++ b/remoting/test/protocol_perftest.cc
@@ -22,12 +22,12 @@ #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" #include "remoting/host/fake_desktop_environment.h" -#include "remoting/host/video_frame_pump.h" #include "remoting/protocol/ice_transport_factory.h" #include "remoting/protocol/jingle_session_manager.h" #include "remoting/protocol/me2me_host_authenticator_factory.h" #include "remoting/protocol/negotiating_client_authenticator.h" #include "remoting/protocol/session_config.h" +#include "remoting/protocol/video_frame_pump.h" #include "remoting/signaling/fake_signal_strategy.h" #include "remoting/test/fake_network_dispatcher.h" #include "remoting/test/fake_port_allocator.h" @@ -82,7 +82,7 @@ : host_thread_("host"), capture_thread_("capture"), encode_thread_("encode") { - VideoFramePump::EnableTimestampsForTests(); + protocol::VideoFramePump::EnableTimestampsForTests(); host_thread_.StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); capture_thread_.Start();
diff --git a/rlz/lib/rlz_lib.h b/rlz/lib/rlz_lib.h index 6e3f451f..afc2314 100644 --- a/rlz/lib/rlz_lib.h +++ b/rlz/lib/rlz_lib.h
@@ -282,7 +282,7 @@ // Set the OEM Deal Confirmation Code (DCC). This information is used for RLZ // initalization. // Access: HKLM write, or -// HKCU read if rlz_lib::CreateMachineState() has been sucessfully called. +// HKCU read if rlz_lib::CreateMachineState() has been successfully called. bool RLZ_LIB_API SetMachineDealCode(const char* dcc); // Get the DCC cgi argument string to append to a daily ping. @@ -337,7 +337,7 @@ // the time skip check is specific to each supplementary brand. class SupplementaryBranding { public: - SupplementaryBranding(const char* brand); + explicit SupplementaryBranding(const char* brand); ~SupplementaryBranding(); static const std::string& GetBrand();
diff --git a/sandbox/win/src/app_container.h b/sandbox/win/src/app_container.h index 8125d70..a08c01b 100644 --- a/sandbox/win/src/app_container.h +++ b/sandbox/win/src/app_container.h
@@ -56,7 +56,7 @@ ResultCode CreateAppContainer(const base::string16& sid, const base::string16& name); -// Deletes an AppContainer previously created with a successfull call to +// Deletes an AppContainer previously created with a successful call to // CreateAppContainer. ResultCode DeleteAppContainer(const base::string16& sid);
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc index ae29eb0..ac3254ad8 100644 --- a/skia/ext/analysis_canvas.cc +++ b/skia/ext/analysis_canvas.cc
@@ -65,7 +65,7 @@ return false; // if the clip is smaller than the canvas, we're partly clipped, so abort. - if (!clip_irect.contains(SkIRect::MakeSize(canvas->getDeviceSize()))) + if (!clip_irect.contains(SkIRect::MakeSize(canvas->getBaseLayerSize()))) return false; const SkMatrix& matrix = canvas->getTotalMatrix(); @@ -450,7 +450,7 @@ ++saved_stack_size_; - SkIRect canvas_ibounds = SkIRect::MakeSize(this->getDeviceSize()); + SkIRect canvas_ibounds = SkIRect::MakeSize(this->getBaseLayerSize()); SkRect canvas_bounds; canvas_bounds.set(canvas_ibounds);
diff --git a/storage/browser/blob/blob_url_request_job.cc b/storage/browser/blob/blob_url_request_job.cc index 6ec2fe5..deea300 100644 --- a/storage/browser/blob/blob_url_request_job.cc +++ b/storage/browser/blob/blob_url_request_job.cc
@@ -75,41 +75,37 @@ weak_factory_.InvalidateWeakPtrs(); } -bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, - int dest_size, - int* bytes_read) { +int BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size) { TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); DCHECK_NE(dest_size, 0); - DCHECK(bytes_read); - // Bail out immediately if we encounter an error. - if (error_) { - *bytes_read = 0; - return true; - } + // Bail out immediately if we encounter an error. This happens if a previous + // ReadRawData signalled an error to its caller but the caller called + // ReadRawData again anyway. + if (error_) + return 0; + int bytes_read = 0; BlobReader::Status read_status = - blob_reader_->Read(dest, dest_size, bytes_read, + blob_reader_->Read(dest, dest_size, &bytes_read, base::Bind(&BlobURLRequestJob::DidReadRawData, weak_factory_.GetWeakPtr())); switch (read_status) { case BlobReader::Status::NET_ERROR: - NotifyFailure(blob_reader_->net_error()); TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); - return false; + return blob_reader_->net_error(); case BlobReader::Status::IO_PENDING: - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); - return false; + return net::ERR_IO_PENDING; case BlobReader::Status::DONE: TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); - return true; + return bytes_read; } NOTREACHED(); - return true; + return 0; } bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const { @@ -222,13 +218,7 @@ void BlobURLRequestJob::DidReadRawData(int result) { TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid", blob_handle_ ? blob_handle_->uuid() : "NotFound"); - if (result < 0) { - NotifyFailure(result); - return; - } - // Clear the IO_PENDING status - SetStatus(net::URLRequestStatus()); - NotifyReadComplete(result); + ReadRawDataComplete(result); } void BlobURLRequestJob::NotifyFailure(int error_code) { @@ -236,11 +226,7 @@ // If we already return the headers on success, we can't change the headers // now. Instead, we just error out. - if (response_info_) { - NotifyDone( - net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code)); - return; - } + DCHECK(!response_info_) << "Cannot NotifyFailure after headers."; net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; switch (error_code) {
diff --git a/storage/browser/blob/blob_url_request_job.h b/storage/browser/blob/blob_url_request_job.h index 21baa2c..1f0b9fb 100644 --- a/storage/browser/blob/blob_url_request_job.h +++ b/storage/browser/blob/blob_url_request_job.h
@@ -44,7 +44,7 @@ // net::URLRequestJob methods. void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; bool GetMimeType(std::string* mime_type) const override; void GetResponseInfo(net::HttpResponseInfo* info) override; int GetResponseCode() const override;
diff --git a/storage/browser/fileapi/file_system_dir_url_request_job.cc b/storage/browser/fileapi/file_system_dir_url_request_job.cc index fc91f3bc..c0537735 100644 --- a/storage/browser/fileapi/file_system_dir_url_request_job.cc +++ b/storage/browser/fileapi/file_system_dir_url_request_job.cc
@@ -14,7 +14,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "net/base/io_buffer.h" -#include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/url_request/url_request.h" #include "storage/browser/fileapi/file_system_context.h" @@ -44,16 +43,14 @@ FileSystemDirURLRequestJob::~FileSystemDirURLRequestJob() { } -bool FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, - int dest_size, - int* bytes_read) { - int count = std::min(dest_size, static_cast<int>(data_.size())); +int FileSystemDirURLRequestJob::ReadRawData(net::IOBuffer* dest, + int dest_size) { + int count = std::min(dest_size, base::checked_cast<int>(data_.size())); if (count > 0) { memcpy(dest->data(), data_.data(), count); data_.erase(0, count); } - *bytes_read = count; - return true; + return count; } void FileSystemDirURLRequestJob::Start() { @@ -99,8 +96,7 @@ false); return; } - NotifyDone( - URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FILE_NOT_FOUND)); + NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); return; } file_system_context_->operation_runner()->ReadDirectory( @@ -113,8 +109,7 @@ file_system_context_->CrackURL(request_->url()).is_valid()) { StartAsync(); } else { - NotifyDone( - URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FILE_NOT_FOUND)); + NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); } } @@ -126,7 +121,7 @@ int rv = net::ERR_FILE_NOT_FOUND; if (result == base::File::FILE_ERROR_INVALID_URL) rv = net::ERR_INVALID_URL; - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); + NotifyStartError(URLRequestStatus::FromError(rv)); return; } @@ -175,7 +170,7 @@ int rv = net::ERR_FILE_NOT_FOUND; if (result == base::File::FILE_ERROR_INVALID_URL) rv = net::ERR_INVALID_URL; - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, rv)); } if (!request_)
diff --git a/storage/browser/fileapi/file_system_dir_url_request_job.h b/storage/browser/fileapi/file_system_dir_url_request_job.h index 01bd372..93fdd1fe 100644 --- a/storage/browser/fileapi/file_system_dir_url_request_job.h +++ b/storage/browser/fileapi/file_system_dir_url_request_job.h
@@ -32,7 +32,7 @@ // URLRequestJob methods: void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; bool GetCharset(std::string* charset) override; // FilterContext methods (via URLRequestJob):
diff --git a/storage/browser/fileapi/file_system_url_request_job.cc b/storage/browser/fileapi/file_system_url_request_job.cc index 8d58f64..8edcb3d 100644 --- a/storage/browser/fileapi/file_system_url_request_job.cc +++ b/storage/browser/fileapi/file_system_url_request_job.cc
@@ -62,6 +62,7 @@ file_system_context_(file_system_context), is_directory_(false), remaining_bytes_(0), + range_parse_result_(net::OK), weak_factory_(this) {} FileSystemURLRequestJob::~FileSystemURLRequestJob() {} @@ -79,39 +80,28 @@ weak_factory_.InvalidateWeakPtrs(); } -bool FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, - int dest_size, - int* bytes_read) { +int FileSystemURLRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size) { DCHECK_NE(dest_size, 0); - DCHECK(bytes_read); DCHECK_GE(remaining_bytes_, 0); if (reader_.get() == NULL) - return false; + return net::ERR_FAILED; if (remaining_bytes_ < dest_size) - dest_size = static_cast<int>(remaining_bytes_); + dest_size = remaining_bytes_; - if (!dest_size) { - *bytes_read = 0; - return true; - } + if (!dest_size) + return 0; const int rv = reader_->Read(dest, dest_size, base::Bind(&FileSystemURLRequestJob::DidRead, weak_factory_.GetWeakPtr())); if (rv >= 0) { - // Data is immediately available. - *bytes_read = rv; remaining_bytes_ -= rv; DCHECK_GE(remaining_bytes_, 0); - return true; } - if (rv == net::ERR_IO_PENDING) - SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); - else - NotifyFailed(rv); - return false; + + return rv; } bool FileSystemURLRequestJob::GetMimeType(std::string* mime_type) const { @@ -126,8 +116,12 @@ void FileSystemURLRequestJob::SetExtraRequestHeaders( const net::HttpRequestHeaders& headers) { std::string range_header; + // Currently this job only cares about the Range header. Note that validation + // is deferred to DidGetMetaData(), because NotifyStartError is not legal to + // call since the job has not started. if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { std::vector<net::HttpByteRange> ranges; + if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { if (ranges.size() == 1) { byte_range_ = ranges[0]; @@ -135,7 +129,7 @@ // We don't support multiple range requests in one single URL request. // TODO(adamk): decide whether we want to support multiple range // requests. - NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); + range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; } } } @@ -167,7 +161,7 @@ } if (!file_system_context_->CanServeURLRequest(url_)) { // In incognito mode the API is not usable and there should be no data. - NotifyFailed(net::ERR_FILE_NOT_FOUND); + NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); return; } file_system_context_->operation_runner()->GetMetadata( @@ -182,7 +176,7 @@ file_system_context_->CrackURL(request_->url()).is_valid()) { StartAsync(); } else { - NotifyFailed(net::ERR_FILE_NOT_FOUND); + NotifyStartError(URLRequestStatus::FromError(net::ERR_FILE_NOT_FOUND)); } } @@ -190,9 +184,10 @@ base::File::Error error_code, const base::File::Info& file_info) { if (error_code != base::File::FILE_OK) { - NotifyFailed(error_code == base::File::FILE_ERROR_INVALID_URL - ? net::ERR_INVALID_URL - : net::ERR_FILE_NOT_FOUND); + NotifyStartError(URLRequestStatus::FromError( + error_code == base::File::FILE_ERROR_INVALID_URL + ? net::ERR_INVALID_URL + : net::ERR_FILE_NOT_FOUND)); return; } @@ -202,8 +197,14 @@ is_directory_ = file_info.is_directory; + if (range_parse_result_ != net::OK) { + NotifyStartError(URLRequestStatus::FromError(range_parse_result_)); + return; + } + if (!byte_range_.ComputeBounds(file_info.size)) { - NotifyFailed(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); + NotifyStartError( + URLRequestStatus::FromError(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); return; } @@ -227,17 +228,12 @@ } void FileSystemURLRequestJob::DidRead(int result) { - if (result > 0) - SetStatus(URLRequestStatus()); // Clear the IO_PENDING status - else if (result == 0) - NotifyDone(URLRequestStatus()); - else - NotifyFailed(result); + if (result >= 0) { + remaining_bytes_ -= result; + DCHECK_GE(remaining_bytes_, 0); + } - remaining_bytes_ -= result; - DCHECK_GE(remaining_bytes_, 0); - - NotifyReadComplete(result); + ReadRawDataComplete(result); } bool FileSystemURLRequestJob::IsRedirectResponse(GURL* location, @@ -257,8 +253,4 @@ return false; } -void FileSystemURLRequestJob::NotifyFailed(int rv) { - NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); -} - } // namespace storage
diff --git a/storage/browser/fileapi/file_system_url_request_job.h b/storage/browser/fileapi/file_system_url_request_job.h index e442cae3..308b66c 100644 --- a/storage/browser/fileapi/file_system_url_request_job.h +++ b/storage/browser/fileapi/file_system_url_request_job.h
@@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "net/url_request/url_request_job.h" #include "storage/browser/fileapi/file_system_url.h" @@ -41,7 +42,7 @@ // URLRequestJob methods: void Start() override; void Kill() override; - bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override; + int ReadRawData(net::IOBuffer* buf, int buf_size) override; bool IsRedirectResponse(GURL* location, int* http_status_code) override; void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; void GetResponseInfo(net::HttpResponseInfo* info) override; @@ -60,7 +61,6 @@ void DidGetMetadata(base::File::Error error_code, const base::File::Info& file_info); void DidRead(int result); - void NotifyFailed(int rv); const std::string storage_domain_; FileSystemContext* file_system_context_; @@ -69,6 +69,7 @@ bool is_directory_; scoped_ptr<net::HttpResponseInfo> response_info_; int64 remaining_bytes_; + net::Error range_parse_result_; net::HttpByteRange byte_range_; base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_;
diff --git a/styleguide/c++/c++11.html b/styleguide/c++/c++11.html index 962de844..cc1bab3 100644 --- a/styleguide/c++/c++11.html +++ b/styleguide/c++/c++11.html
@@ -298,6 +298,18 @@ </tr> <tr> +<td>Begin and End Non-Member Functions</td> +<td><code>std::begin()</code> and <code>std::end()</code></td> +<td>Allows use of free functions on any container, including +fixed-size arrays</td> +<td><a href="http://en.cppreference.com/w/cpp/iterator/begin"> +std::begin</a> and +<a href="http://en.cppreference.com/w/cpp/iterator/end"> +std::end</a></td> +<td>Useful for fixed-size arrays. <a href="https://groups.google.com/a/chromium.org/d/topic/cxx/5iFNE8P5qT4/discussion">Discussion thread</a></td> +</tr> + +<tr> <td>Containers containing movable types</td> <td><code>vector<scoped_ptr></code></td> <td>Enables containers that contain move-only types like <code>scoped_ptr</code></td> @@ -682,18 +694,6 @@ </tr> <tr> -<td>Begin and End Non-Member Functions</td> -<td><code>std::begin()</code> and <code>std::end()</code></td> -<td>Allows use of free functions on any container, including -built-in arrays</td> -<td><a href="http://en.cppreference.com/w/cpp/iterator/begin"> -std::begin</a> and -<a href="http://en.cppreference.com/w/cpp/iterator/end"> -std::end</a></td> -<td>Useful for built-in arrays.</td> -</tr> - -<tr> <td>Bind Operations</td> <td><code>std::bind(<i>function</i>, <i>args</i>, ...)</code></td> <td>Declares a function object bound to certain arguments</td>
diff --git a/sync/BUILD.gn b/sync/BUILD.gn index 664fa462..b6a76af 100644 --- a/sync/BUILD.gn +++ b/sync/BUILD.gn
@@ -26,6 +26,8 @@ "api/attachments/attachment_store_backend.cc", "api/attachments/attachment_store_backend.h", "api/data_batch.h", + "api/entity_change.cc", + "api/entity_change.h", "api/entity_data.cc", "api/entity_data.h", "api/metadata_batch.h",
diff --git a/sync/android/javatests/src/org/chromium/sync/AndroidSyncSettingsTest.java b/sync/android/javatests/src/org/chromium/sync/AndroidSyncSettingsTest.java index e89c338..fc2c382d 100644 --- a/sync/android/javatests/src/org/chromium/sync/AndroidSyncSettingsTest.java +++ b/sync/android/javatests/src/org/chromium/sync/AndroidSyncSettingsTest.java
@@ -11,7 +11,6 @@ import android.test.suitebuilder.annotation.SmallTest; import org.chromium.base.ThreadUtils; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.sync.AndroidSyncSettings.AndroidSyncSettingsObserver; import org.chromium.sync.signin.AccountManagerHelper; @@ -312,10 +311,8 @@ AndroidSyncSettings.getContractAuthority(mContext)); } - /*@SmallTest - @Feature({"Sync"})*/ - // http://crbug.com/527856 - @DisabledTest + @SmallTest + @Feature({"Sync"}) public void testAndroidSyncSettingsPostsNotifications() throws InterruptedException { // Turn on syncability. mSyncContentResolverDelegate.setMasterSyncAutomatically(true);
diff --git a/sync/api/entity_change.cc b/sync/api/entity_change.cc new file mode 100644 index 0000000..e2f2bedb9 --- /dev/null +++ b/sync/api/entity_change.cc
@@ -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. + +#include "sync/api/entity_change.h" + +namespace syncer_v2 { + +// static +EntityChange EntityChange::CreateAdd(std::string client_key, + EntityDataPtr data) { + return EntityChange(client_key, ACTION_ADD, data); +} + +// static +EntityChange EntityChange::CreateUpdate(std::string client_key, + EntityDataPtr data) { + return EntityChange(client_key, ACTION_UPDATE, data); +} + +// static +EntityChange EntityChange::CreateDelete(std::string client_key) { + return EntityChange(client_key, ACTION_DELETE, EntityDataPtr()); +} + +EntityChange::EntityChange(std::string client_key, + ChangeType type, + EntityDataPtr data) + : client_key_(client_key), type_(type), data_(data){}; + +EntityChange::~EntityChange() {} + +} // namespace syncer_v2
diff --git a/sync/api/entity_change.h b/sync/api/entity_change.h new file mode 100644 index 0000000..88e3812 --- /dev/null +++ b/sync/api/entity_change.h
@@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SYNC_API_ENTITY_CHANGE_H_ +#define SYNC_API_ENTITY_CHANGE_H_ + +#include <string> +#include <vector> + +#include "sync/api/entity_data.h" +#include "sync/base/sync_export.h" + +namespace syncer_v2 { + +class SYNC_EXPORT EntityChange { + public: + enum ChangeType { + ACTION_ADD, + ACTION_UPDATE, + ACTION_DELETE + }; + + static EntityChange CreateAdd(std::string client_key, EntityDataPtr data); + static EntityChange CreateUpdate(std::string client_key, EntityDataPtr data); + static EntityChange CreateDelete(std::string client_key); + + virtual ~EntityChange(); + + std::string client_key() const { return client_key_; } + ChangeType type() const { return type_; } + const EntityData& data() const { return data_.value(); } + + private: + EntityChange(std::string client_key, ChangeType type, EntityDataPtr data); + + const std::string client_key_; + const ChangeType type_; + const EntityDataPtr data_; +}; + +typedef std::vector<EntityChange> EntityChangeList; + +} // namespace syncer_v2 + +#endif // SYNC_API_ENTITY_CHANGE_H_
diff --git a/sync/api/model_type_service.h b/sync/api/model_type_service.h index 473c9c172..c09271b 100644 --- a/sync/api/model_type_service.h +++ b/sync/api/model_type_service.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" +#include "sync/api/entity_change.h" #include "sync/api/entity_data.h" #include "sync/api/model_type_change_processor.h" #include "sync/base/sync_export.h" @@ -49,10 +50,9 @@ EntityDataList entity_data_list) = 0; // Apply changes from the sync server locally. - // TODO(skym): The change type should be in here somehow. virtual syncer::SyncError ApplySyncChanges( MetadataChanges* metadata_changes, - EntityDataList entity_data_list) = 0; + EntityChangeList entity_changes) = 0; // Asynchronously retrieve the sync metadata. virtual void LoadMetadata(MetadataCallback callback) = 0;
diff --git a/sync/engine/sync_scheduler_unittest.cc b/sync/engine/sync_scheduler_unittest.cc index 9f621a09..dbf6fda 100644 --- a/sync/engine/sync_scheduler_unittest.cc +++ b/sync/engine/sync_scheduler_unittest.cc
@@ -719,7 +719,6 @@ PumpLoop(); ASSERT_EQ(0, ready_counter.times_called()); ASSERT_EQ(1, retry_counter.times_called()); - } TEST_F(SyncSchedulerTest, ThrottlingExpiresFromPoll) { @@ -1084,7 +1083,6 @@ PumpLoop(); ASSERT_EQ(0, ready_counter.times_called()); ASSERT_EQ(1, retry_counter.times_called()); - } // Test that backoff is shaping traffic properly with consecutive errors. @@ -1201,7 +1199,7 @@ StartSyncScheduler(base::Time()); - // Run the unsucessful poll. The failed poll should not trigger backoff. + // Run the unsuccessful poll. The failed poll should not trigger backoff. RunLoop(); EXPECT_TRUE(scheduler()->IsBackingOff());
diff --git a/sync/internal_api/http_bridge.cc b/sync/internal_api/http_bridge.cc index 6da0dd3..68d2762f 100644 --- a/sync/internal_api/http_bridge.cc +++ b/sync/internal_api/http_bridge.cc
@@ -7,6 +7,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" +#include "base/metrics/sparse_histogram.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -432,6 +433,10 @@ if (fetch_state_.request_succeeded) LogTimeout(false); + UMA_HISTOGRAM_SPARSE_SLOWLY("Sync.URLFetchResponse", + source->GetStatus().is_success() + ? source->GetResponseCode() + : source->GetStatus().ToNetError()); UMA_HISTOGRAM_LONG_TIMES("Sync.URLFetchTime", fetch_state_.end_time - fetch_state_.start_time);
diff --git a/sync/sync.gyp b/sync/sync.gyp index 0690495..bd41f74 100644 --- a/sync/sync.gyp +++ b/sync/sync.gyp
@@ -77,6 +77,8 @@ 'api/attachments/attachment_store_backend.cc', 'api/attachments/attachment_store_backend.h', 'api/data_batch.h', + 'api/entity_change.cc', + 'api/entity_change.h', 'api/entity_data.cc', 'api/entity_data.h', 'api/metadata_batch.h',
diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc index afac3be..a999bf6 100644 --- a/sync/syncable/directory.cc +++ b/sync/syncable/directory.cc
@@ -1324,7 +1324,7 @@ } // If the next check failed, it would imply that an item exists // on the server, isn't waiting for application locally, but either - // is an unsynced create or a sucessful delete in the local copy. + // is an unsynced create or a successful delete in the local copy. // Either way, that's a mismatch. if (!SyncAssert(0 == server_version, FROM_HERE, "Server version should be zero.",
diff --git a/testing/android/native_test/native_test_launcher.cc b/testing/android/native_test/native_test_launcher.cc index 0f14ff9..9ff995c 100644 --- a/testing/android/native_test/native_test_launcher.cc +++ b/testing/android/native_test/native_test_launcher.cc
@@ -76,8 +76,8 @@ base::CommandLine::Init(arraysize(kInitialArgv), kInitialArgv); // Set the application context in base. - base::android::InitApplicationContext(env, app_context); base::android::RegisterJni(env); + base::android::InitApplicationContext(env, app_context); std::vector<std::string> args;
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index a1959fe..df07c80 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -301,8 +301,8 @@ "Linux Builder": { "additional_compile_targets": [ "blimp", - "components/mus/example:all", "mandoline:all", + "mash:all", "remoting_all" ] }, @@ -504,6 +504,9 @@ "test": "jingle_unittests" }, { + "test": "mash_unittests" + }, + { "swarming": { "can_use_on_swarming_builders": true }, @@ -570,9 +573,6 @@ "test": "mojo_view_manager_lib_unittests" }, { - "test": "mustash_unittests" - }, - { "swarming": { "can_use_on_swarming_builders": true },
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json index 86e83f4..0e32301 100644 --- a/testing/buildbot/chromium.webkit.json +++ b/testing/buildbot/chromium.webkit.json
@@ -840,6 +840,25 @@ }, { "swarming": { + "can_use_on_swarming_builders": true, + "shards": 20 + }, + "test": "browser_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_browsertests" + }, + { + "swarming": { "can_use_on_swarming_builders": true }, "test": "webkit_unit_tests"
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 643b3c8a..265064f 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -1558,7 +1558,6 @@ "chromedriver_unittests", "components_browsertests", "components_unittests", - "components/mus/example:all", "compositor_unittests", "content_unittests", "courgette_unittests", @@ -1576,6 +1575,7 @@ "jingle_unittests", "keyboard_unittests", "mandoline:all", + "mash:all", "media_unittests", "media_blink_unittests", "message_center_unittests", @@ -1641,7 +1641,7 @@ "test": "mojo_view_manager_lib_unittests" }, { - "test": "mustash_unittests" + "test": "mash_unittests" }, { "test": "resource_provider_unittests"
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 07fa7f6..101404ae 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -308,8 +308,8 @@ "label": "//ui/message_center:message_center_unittests", "type": "unknown", }, - "mustash_unittests": { - "label": "//components/mus/example:mustash_unittests", + "mash_unittests": { + "label": "//mash:mash_unittests", "type": "unknown", }, "nacl_loader_unittests": {
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index 740bcef..b64bc225 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -164,6 +164,7 @@ "url_parse_fuzzer.cc", ] deps = [ + "//base", "//base:i18n", "//testing/libfuzzer:libfuzzer_main", "//url:url", @@ -194,3 +195,13 @@ "$root_out_dir/snapshot_blob.bin", ] } + +test("base_json_reader_fuzzer") { + sources = [ + "base_json_reader_fuzzer.cc", + ] + deps = [ + "//base", + "//testing/libfuzzer:libfuzzer_main", + ] +}
diff --git a/testing/libfuzzer/fuzzers/base_json_reader_fuzzer.cc b/testing/libfuzzer/fuzzers/base_json_reader_fuzzer.cc new file mode 100644 index 0000000..d275654b --- /dev/null +++ b/testing/libfuzzer/fuzzers/base_json_reader_fuzzer.cc
@@ -0,0 +1,17 @@ +// 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 <string> + +#include "base/json/json_reader.h" +#include "base/values.h" + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, + unsigned long size) { + base::JSONReader reader; + reader.Read(std::string(reinterpret_cast<const char*>(data), size)); + return 0; +} +
diff --git a/testing/test.gni b/testing/test.gni index a6daf7e..a280a1b 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -64,6 +64,13 @@ } unittest_apk(apk_name) { + forward_variables_from(invoker, + [ + "android_manifest", + "use_default_launcher", + "write_asset_list", + ]) + unittests_dep = ":$library_name" apk_name = main_target_name if (defined(invoker.output_name)) { @@ -79,12 +86,6 @@ if (defined(invoker.apk_asset_location)) { asset_location = invoker.apk_asset_location } - if (defined(invoker.android_manifest)) { - android_manifest = invoker.android_manifest - } - if (defined(invoker.use_default_launcher)) { - use_default_launcher = invoker.use_default_launcher - } } _test_name = main_target_name
diff --git a/testing/variations/fieldtrial_testing_config_win.json b/testing/variations/fieldtrial_testing_config_win.json index 98eaeb3..722183a1 100644 --- a/testing/variations/fieldtrial_testing_config_win.json +++ b/testing/variations/fieldtrial_testing_config_win.json
@@ -217,6 +217,11 @@ "group_name": "Enabled" } ], + "TriggeredResetFieldTrial": [ + { + "group_name": "On" + } + ], "UseDelayAgnosticAEC": [ { "group_name": "DefaultEnabled"
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 91d5e83f..570dc3c 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -449,6 +449,27 @@ crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/styles/test-010.html [ Failure Crash ] crbug.com/505364 imported/web-platform-tests/shadow-dom/untriaged/user-interaction/ranges-and-selections/test-002.html [ Failure Crash ] +crbug.com/481585 compositing/backface-visibility-transformed.html [ NeedsRebaseline ] +crbug.com/481585 compositing/geometry/layer-due-to-layer-children-deep.html [ NeedsRebaseline ] +crbug.com/481585 compositing/geometry/layer-due-to-layer-children.html [ NeedsRebaseline ] +crbug.com/481585 compositing/geometry/vertical-scroll-composited.html [ NeedsRebaseline ] +crbug.com/481585 compositing/overflow/nested-render-surfaces-with-rotation.html [ NeedsRebaseline ] +crbug.com/481585 compositing/perpendicular-layer-sorting.html [ NeedsRebaseline ] +crbug.com/481585 compositing/reflections/nested-reflection-anchor-point.html [ NeedsRebaseline ] +crbug.com/481585 compositing/reflections/nested-reflection-animated.html [ NeedsRebaseline ] +crbug.com/481585 compositing/reflections/transform-inside-reflection.html [ NeedsRebaseline ] +crbug.com/481585 css3/blending/background-blend-mode-overlapping-accelerated-elements.html [ NeedsRebaseline ] +crbug.com/481585 fast/sub-pixel/transformed-iframe-copy-on-scroll.html [ NeedsRebaseline ] +crbug.com/481585 media/video-layer-crash.html [ NeedsRebaseline ] +crbug.com/481585 media/video-transformed.html [ NeedsRebaseline ] +crbug.com/481585 transforms/3d/general/perspective-units.html [ NeedsRebaseline ] +crbug.com/481585 transforms/3d/general/transform-origin-z-change.html [ NeedsRebaseline ] +crbug.com/481585 transforms/3d/point-mapping/3d-point-mapping-coplanar.html [ NeedsRebaseline ] +crbug.com/481585 transforms/3d/point-mapping/3d-point-mapping-deep.html [ NeedsRebaseline ] +crbug.com/481585 transforms/3d/point-mapping/3d-point-mapping-origins.html [ NeedsRebaseline ] +crbug.com/481585 transforms/3d/point-mapping/3d-point-mapping.html [ NeedsRebaseline ] +crbug.com/481585 virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation.html [ NeedsRebaseline ] + crbug.com/552532 [ Win10 ] fast/replaced/no-focus-ring-embed.html [ Pass Crash ] crbug.com/552532 [ Win10 ] fast/replaced/no-focus-ring-object.html [ Pass Crash ] crbug.com/552532 [ Win10 ] plugins/focus.html [ Pass Crash ] @@ -483,6 +504,8 @@ crbug.com/412381 imported/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-trivial-constraint.html [ Failure ] crbug.com/412381 imported/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/unknownkey-option-param.html [ Failure ] +crbug.com/559240 virtual/gpu/fast/canvas/canvas-imageSmoothingQuality-pixel.html [ NeedsRebaseline ] + crbug.com/325673 imported/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars-first-char.html [ Failure Timeout ] crbug.com/325673 imported/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars.html [ Failure Timeout ] crbug.com/325673 imported/web-platform-tests/custom-elements/concepts/custom-elements-type-naming.html [ Failure ] @@ -652,7 +675,6 @@ crbug.com/492664 imported/csswg-test/css-writing-modes-3/inline-block-alignment-007.xht [ Failure ] crbug.com/492664 imported/csswg-test/css-writing-modes-3/inline-table-alignment-003.xht [ Failure ] crbug.com/492664 imported/csswg-test/css-writing-modes-3/inline-table-alignment-005.xht [ Failure ] -crbug.com/491454 imported/csswg-test/css-writing-modes-3/outline-inline-vrl-006.html [ Failure ] crbug.com/492664 imported/csswg-test/css-writing-modes-3/table-column-order-002.xht [ Failure ] crbug.com/492664 imported/csswg-test/css-writing-modes-3/table-column-order-003.xht [ Failure ] crbug.com/492664 imported/csswg-test/css-writing-modes-3/table-column-order-004.xht [ Failure ] @@ -763,6 +785,8 @@ crbug.com/484370 [ Win Debug ] svg/custom/gradient-userSpaceOnUse-with-percentage.svg [ Failure ] +crbug.com/116710 [ Win Debug ] transforms/3d/point-mapping/3d-point-mapping-preserve-3d.html [ Failure ] + # Printing Layout broken in these tests. crbug.com/377696 printing/setPrinting.html [ Skip ] crbug.com/377696 printing/width-overflow.html [ Skip ] @@ -1295,6 +1319,9 @@ crbug.com/550285 [ XP ] virtual/syncpaint/inspector/tracing/decode-resize.html [ Slow Pass Failure ] +crbug.com/560652 [ Mac ] editing/selection/vertical-rl-rtl-extend-line-forward-p.html [ Failure ] +crbug.com/560652 [ Mac ] editing/selection/vertical-rl-rtl-extend-line-forward-br.html [ Failure ] + crbug.com/474759 fast/writing-mode/vertical-rl-replaced-selection.html [ Failure ] crbug.com/474759 fast/block/line-layout/selection-highlight-overlap.html [ Failure ] crbug.com/502927 [ XP ] paint/frames/frameset-with-stacking-context-and-not-stacking-context-children.html [ Failure ] @@ -1304,6 +1331,10 @@ crbug.com/353746 virtual/android/fullscreen/video-specified-size.html [ Failure Pass ] +crbug.com/560503 fast/js/mozilla/strict/12.14.1.html [ NeedsManualRebaseline ] +crbug.com/560503 fast/js/mozilla/strict/13.1.html [ NeedsManualRebaseline ] +crbug.com/560503 fast/js/mozilla/strict/regress-532254.html [ NeedsManualRebaseline ] + crbug.com/527270 accessibility/name-calc-img.html [ Failure Pass Timeout ] # This test has different results in Debug and Release. @@ -1347,6 +1378,4 @@ crbug.com/548765 http/tests/inspector/console-fetch-logging.html [ Failure Pass Slow ] -crbug.com/559300 inspector/layers/layer-canvas-log.html [ Failure ] - crbug.com/549314 [ XP ] inspector-protocol/layout-fonts/unicode-range-combining-chars-fallback.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-baseFrequency-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-baseFrequency-composition.html new file mode 100644 index 0000000..fd00993 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-baseFrequency-composition.html
@@ -0,0 +1,139 @@ +<!DOCTYPE html> +<html> +<body> +<template id="target-template"> +<svg xmlns="http://www.w3.org/2000/svg" width="90" height="90"> +<feTurbulence class="target" /> +</svg> +</template> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> +<script> +'use strict'; +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '0', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, -3'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2, 3'}, + {at: 0.6, is: '4, 7'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '8, 15'}, +]); + +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '3', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '2, 0'}, + {at: 0, is: '4, 4'}, + {at: 0.2, is: '5, 6'}, + {at: 0.6, is: '7, 10'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '11, 18'}, +]); + +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '3', + from: '1', + fromComposite: 'replace', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-2.2, -4.2'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2.6, 3.6'}, + {at: 0.6, is: '5.8, 8.8'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '12.2, 19.2'}, +]); + +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '3', + from: neutralKeyframe, + to: '6 11', + toComposite: 'replace', +}, [ + {at: -0.4, is: '1.8, -0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3.6, 4.6'}, + {at: 0.6, is: '4.8, 7.8'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '7.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '0', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-4, 10'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-1, 10'}, + {at: 0.6, is: '1, 10'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '5, 10'}, +]); + +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '3', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, 13'}, + {at: 0, is: '1, 13'}, + {at: 0.2, is: '2, 13'}, + {at: 0.6, is: '4, 13'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '8, 13'}, +]); + +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '3', + from: '-2 10', + fromComposite: 'replace', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-5.2, 8.8'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-0.4, 10.6'}, + {at: 0.6, is: '2.8, 11.8'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '9.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'baseFrequency', + underlying: '3', + from: neutralKeyframe, + to: '3 10', + toComposite: 'replace', +}, [ + {at: -0.4, is: '3, 0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3, 4.4'}, + {at: 0.6, is: '3, 7.2'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '3, 12.8'}, +]); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-kernelUnitLength-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-kernelUnitLength-composition.html new file mode 100644 index 0000000..3169dc2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-kernelUnitLength-composition.html
@@ -0,0 +1,139 @@ +<!DOCTYPE html> +<html> +<body> +<template id="target-template"> +<svg width="90" height="90"> +<feDiffuseLighting class="target" /> +</svg> +</template> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> +<script> +'use strict'; +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '0', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, -3'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2, 3'}, + {at: 0.6, is: '4, 7'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '8, 15'}, +]); + +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '3', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '2, 0'}, + {at: 0, is: '4, 4'}, + {at: 0.2, is: '5, 6'}, + {at: 0.6, is: '7, 10'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '11, 18'}, +]); + +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '3', + from: '1', + fromComposite: 'replace', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-2.2, -4.2'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2.6, 3.6'}, + {at: 0.6, is: '5.8, 8.8'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '12.2, 19.2'}, +]); + +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '3', + from: neutralKeyframe, + to: '6 11', + toComposite: 'replace', +}, [ + {at: -0.4, is: '1.8, -0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3.6, 4.6'}, + {at: 0.6, is: '4.8, 7.8'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '7.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '0', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-4, 10'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-1, 10'}, + {at: 0.6, is: '1, 10'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '5, 10'}, +]); + +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '3', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, 13'}, + {at: 0, is: '1, 13'}, + {at: 0.2, is: '2, 13'}, + {at: 0.6, is: '4, 13'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '8, 13'}, +]); + +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '3', + from: '-2 10', + fromComposite: 'replace', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-5.2, 8.8'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-0.4, 10.6'}, + {at: 0.6, is: '2.8, 11.8'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '9.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'kernelUnitLength', + underlying: '3', + from: neutralKeyframe, + to: '3 10', + toComposite: 'replace', +}, [ + {at: -0.4, is: '3, 0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3, 4.4'}, + {at: 0.6, is: '3, 7.2'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '3, 12.8'}, +]); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-order-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-order-composition.html new file mode 100644 index 0000000..ff5ecb8d --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-order-composition.html
@@ -0,0 +1,64 @@ +<!DOCTYPE html> +<html> +<body> +<template id="target-template"> +<svg width="0" height="0"> + <defs> + <filter> + <feConvolveMatrix kernelMatrix="100 200 300 400" class="target" /> + </filter> + </defs> +</svg> +</template> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> +<script> +'use strict'; +assertAttributeInterpolation({ + property: 'order', + underlying: '1', + from: '1, 6', + fromComposite: 'add', + to: '3, 4', + toComposite: 'add', +}, [ + {at: -0.4, is: '1, 8'}, + {at: 0, is: '2, 7'}, + {at: 0.2, is: '2, 7'}, + {at: 0.6, is: '3, 6'}, + {at: 1, is: '4, 5'}, + {at: 1.4, is: '5, 4'}, +]); + +assertAttributeInterpolation({ + property: 'order', + underlying: '3', + from: '1, 3', + fromComposite: 'replace', + to: '3', + toComposite: 'add', +}, [ + {at: -0.4, is: '1, 2'}, + {at: 0, is: '1, 3'}, + {at: 0.2, is: '2, 4'}, + {at: 0.6, is: '4, 5'}, + {at: 1, is: '6, 6'}, + {at: 1.4, is: '8, 7'}, +]); + +assertAttributeInterpolation({ + property: 'order', + underlying: '3, 5', + from: neutralKeyframe, + to: '1', + toComposite: 'replace', +}, [ + {at: -0.4, is: '4, 7'}, + {at: 0, is: '3, 5'}, + {at: 0.2, is: '3, 4'}, + {at: 0.6, is: '2, 3'}, + {at: 1, is: '1, 1'}, + {at: 1.4, is: '1, 1'}, +]); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-radius-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-radius-composition.html new file mode 100644 index 0000000..fdf86d9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-radius-composition.html
@@ -0,0 +1,139 @@ +<!DOCTYPE html> +<html> +<body> +<template id="target-template"> +<svg width="90" height="90"> +<feMorphology class="target" /> +</svg> +</template> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> +<script> +'use strict'; +assertAttributeInterpolation({ + property: 'radius', + underlying: '0', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, -3'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2, 3'}, + {at: 0.6, is: '4, 7'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '8, 15'}, +]); + +assertAttributeInterpolation({ + property: 'radius', + underlying: '3', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '2, 0'}, + {at: 0, is: '4, 4'}, + {at: 0.2, is: '5, 6'}, + {at: 0.6, is: '7, 10'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '11, 18'}, +]); + +assertAttributeInterpolation({ + property: 'radius', + underlying: '3', + from: '1', + fromComposite: 'replace', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-2.2, -4.2'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2.6, 3.6'}, + {at: 0.6, is: '5.8, 8.8'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '12.2, 19.2'}, +]); + +assertAttributeInterpolation({ + property: 'radius', + underlying: '3', + from: neutralKeyframe, + to: '6 11', + toComposite: 'replace', +}, [ + {at: -0.4, is: '1.8, -0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3.6, 4.6'}, + {at: 0.6, is: '4.8, 7.8'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '7.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'radius', + underlying: '0', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-4, 10'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-1, 10'}, + {at: 0.6, is: '1, 10'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '5, 10'}, +]); + +assertAttributeInterpolation({ + property: 'radius', + underlying: '3', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, 13'}, + {at: 0, is: '1, 13'}, + {at: 0.2, is: '2, 13'}, + {at: 0.6, is: '4, 13'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '8, 13'}, +]); + +assertAttributeInterpolation({ + property: 'radius', + underlying: '3', + from: '-2 10', + fromComposite: 'replace', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-5.2, 8.8'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-0.4, 10.6'}, + {at: 0.6, is: '2.8, 11.8'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '9.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'radius', + underlying: '3', + from: neutralKeyframe, + to: '3 10', + toComposite: 'replace', +}, [ + {at: -0.4, is: '3, 0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3, 4.4'}, + {at: 0.6, is: '3, 7.2'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '3, 12.8'}, +]); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-stdDeviation-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-stdDeviation-composition.html new file mode 100644 index 0000000..7e79c50e --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-stdDeviation-composition.html
@@ -0,0 +1,145 @@ +<!DOCTYPE html> +<html> +<body> +<template id="target-template"> +<svg width="90" height="90"> +<defs> +<filter> +<feGaussianBlur class="target" /> +</filter> +</defs> +</svg> +</template> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> +<script> +'use strict'; +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '0', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, -3'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2, 3'}, + {at: 0.6, is: '4, 7'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '8, 15'}, +]); + +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '3', + from: '1', + fromComposite: 'add', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '2, 0'}, + {at: 0, is: '4, 4'}, + {at: 0.2, is: '5, 6'}, + {at: 0.6, is: '7, 10'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '11, 18'}, +]); + +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '3', + from: '1', + fromComposite: 'replace', + to: '6 11', + toComposite: 'add', +}, [ + {at: -0.4, is: '-2.2, -4.2'}, + {at: 0, is: '1, 1'}, + {at: 0.2, is: '2.6, 3.6'}, + {at: 0.6, is: '5.8, 8.8'}, + {at: 1, is: '9, 14'}, + {at: 1.4, is: '12.2, 19.2'}, +]); + +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '3', + from: neutralKeyframe, + to: '6 11', + toComposite: 'replace', +}, [ + {at: -0.4, is: '1.8, -0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3.6, 4.6'}, + {at: 0.6, is: '4.8, 7.8'}, + {at: 1, is: '6, 11'}, + {at: 1.4, is: '7.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '0', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-4, 10'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-1, 10'}, + {at: 0.6, is: '1, 10'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '5, 10'}, +]); + +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '3', + from: '-2 10', + fromComposite: 'add', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-1, 13'}, + {at: 0, is: '1, 13'}, + {at: 0.2, is: '2, 13'}, + {at: 0.6, is: '4, 13'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '8, 13'}, +]); + +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '3', + from: '-2 10', + fromComposite: 'replace', + to: '3 10', + toComposite: 'add', +}, [ + {at: -0.4, is: '-5.2, 8.8'}, + {at: 0, is: '-2, 10'}, + {at: 0.2, is: '-0.4, 10.6'}, + {at: 0.6, is: '2.8, 11.8'}, + {at: 1, is: '6, 13'}, + {at: 1.4, is: '9.2, 14.2'}, +]); + +assertAttributeInterpolation({ + property: 'stdDeviation', + underlying: '3', + from: neutralKeyframe, + to: '3 10', + toComposite: 'replace', +}, [ + {at: -0.4, is: '3, 0.2'}, + {at: 0, is: '3, 3'}, + {at: 0.2, is: '3, 4.4'}, + {at: 0.6, is: '3, 7.2'}, + {at: 1, is: '3, 10'}, + {at: 1.4, is: '3, 12.8'}, +]); + + +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-viewBox-composition.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-viewBox-composition.html new file mode 100644 index 0000000..b8451dc --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-composition/svg-viewBox-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<html> +<body> +<template id="target-template"> +<svg width="0" height="0"> + <defs> + <marker class="target" /> + </defs> +</svg> +</template> +<script src="../svg-attribute-interpolation/resources/interpolation-test.js"></script> +<script> +'use strict'; +assertAttributeInterpolation({ + property: 'viewBox', + underlying: '10, 10, 10, 10', + from: '10, 20, 80, 90', + fromComposite: 'add', + to: '20, 30, 70, 80', + toComposite: 'add', +}, [ + {at: -0.4, is: '16, 26, 94, 104'}, + {at: 0, is: '20, 30, 90, 100'}, + {at: 0.2, is: '22, 32, 88, 98'}, + {at: 0.6, is: '26, 36, 84, 94'}, + {at: 1, is: '30, 40, 80, 90'}, + {at: 1.4, is: '34, 44, 76, 86'}, +]); + +assertAttributeInterpolation({ + property: 'viewBox', + underlying: '10, 10, 10, 10', + from: '10, 20, 80, 90', + fromComposite: 'add', + to: '20, 30, 70, 80', + toComposite: 'replace', +}, [ + {at: -0.4, is: '20, 30, 98, 108'}, + {at: 0, is: '20, 30, 90, 100'}, + {at: 0.2, is: '20, 30, 86, 96'}, + {at: 0.6, is: '20, 30, 78, 88'}, + {at: 1, is: '20, 30, 70, 80'}, + {at: 1.4, is: '20, 30, 62, 72'}, +]); + +assertAttributeInterpolation({ + property: 'viewBox', + underlying: '10, 10, 10, 10', + from: '10, 20, 80, 90', + fromComposite: 'replace', + to: '20, 30, 70, 80', + toComposite: 'add', +}, [ + {at: -0.4, is: '2, 12, 80, 90'}, + {at: 0, is: '10, 20, 80, 90'}, + {at: 0.2, is: '14, 24, 80, 90'}, + {at: 0.6, is: '22, 32, 80, 90'}, + {at: 1, is: '30, 40, 80, 90'}, + {at: 1.4, is: '38, 48, 80, 90'}, +]); + +assertAttributeInterpolation({ + property: 'viewBox', + underlying: '10, 20, 80, 90', + from: neutralKeyframe, + to: '20, 30, 70, 80', + toComposite: 'replace', +}, [ + {at: -0.4, is: '6, 16, 84, 94'}, + {at: 0, is: '10, 20, 80, 90'}, + {at: 0.2, is: '12, 22, 78, 88'}, + {at: 0.6, is: '16, 26, 74, 84'}, + {at: 1, is: '20, 30, 70, 80'}, + {at: 1.4, is: '24, 34, 66, 76'}, +]); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/resources/interpolation-test.js b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/resources/interpolation-test.js index 923c5879..edb6b68 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/resources/interpolation-test.js +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/resources/interpolation-test.js
@@ -139,7 +139,7 @@ } function serializeSVGRect(rect) { - return String([rect.x, rect.y, rect.width, rect.height]); + return [rect.x, rect.y, rect.width, rect.height].join(', '); } function serializeSVGTransformList(transformList) { @@ -410,8 +410,8 @@ assertionCode += `\n}, [\n`; rebaseline.appendChild(document.createTextNode(assertionCode)); - var rebaselineExpectation; - rebaseline.appendChild(rebaselineExpectation = document.createTextNode('')); + var rebaselineExpectation = document.createTextNode(''); + rebaseline.appendChild(rebaselineExpectation); rebaseline.appendChild(document.createTextNode(']);\n\n')); }
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-backward-br.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-backward-br.html index b5164e6..cef4941e 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-backward-br.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-backward-br.html
@@ -1,21 +1,23 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "ある。" and "名前はまだ" must be selected.</p> -<div id="test" style="height: 30ex; -webkit-writing-mode: vertical-lr; outline: none;" contenteditable> -<p>吾輩は猫である。<br>名前はまだ無い。</p> +<div style="height: 30ex; -webkit-writing-mode: vertical-lr; outline: none;" contenteditable> +<p id="p1">吾輩は猫である。<br>名前はまだ無い。</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.lastChild, 5); + selection.modify('Extend', 'Backward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].lastChild, 5); -window.getSelection().modify('Extend', 'Backward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.lastChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 5, 'anchorOffset'); + assert_equals(selection.focusNode, p1.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-forward-br.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-forward-br.html index b365a5bd..7f3175f 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-forward-br.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-lr-ltr-extend-line-forward-br.html
@@ -1,21 +1,23 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "は猫である。" and "名前" must be selected.</p> -<div id="test" style="height: 30ex; -webkit-writing-mode: vertical-lr; outline: none;" contenteditable> -<p>吾輩は猫である。<br>名前はまだ無い。</p> +<div style="height: 30ex; -webkit-writing-mode: vertical-lr; outline: none;" contenteditable> +<p id="p1">吾輩は猫である。<br>名前はまだ無い。</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.firstChild, 2); + selection.modify('Extend', 'Forward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].firstChild, 2); -window.getSelection().modify('Extend', 'Forward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 2, 'anchorOffset'); + assert_equals(selection.focusNode, p1.lastChild, 'focusNode'); + assert_equals(selection.focusOffset, 2, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-br.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-br.html index e771279..537829a 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-br.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-br.html
@@ -1,21 +1,23 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "ある。" and "名前はまだ" must be selected.</p> -<div id="test" style="height: 30ex; -webkit-writing-mode: vertical-rl; outline: none;" contenteditable> -<p>吾輩は猫である。<br>名前はまだ無い。</p> +<div style="height: 30ex; -webkit-writing-mode: vertical-rl; outline: none;" contenteditable> +<p id="p1">吾輩は猫である。<br>名前はまだ無い。</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.lastChild, 5); + selection.modify('Extend', 'Backward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].lastChild, 5); -window.getSelection().modify('Extend', 'Backward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.lastChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 5, 'anchorOffset'); + assert_equals(selection.focusNode, p1.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-p.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-p.html index ea7d473..f430884f 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-p.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-p.html
@@ -1,22 +1,25 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "ある。" and "名前はまだ" must be selected.</p> -<div id="test" style="height: 30ex; -webkit-writing-mode: vertical-rl; outline: none;" contenteditable> -<p>吾輩は猫である。</p> -<p>名前はまだ無い。</p> +<div style="height: 30ex; -webkit-writing-mode: vertical-rl; outline: none;" contenteditable> +<p id="p1">吾輩は猫である。</p> +<p id="p2">名前はまだ無い。</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + var p2 = document.getElementById('p2'); + selection.collapse(p2.firstChild, 5); + selection.modify('Extend', 'Backward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[1].lastChild, 5); -window.getSelection().modify('Extend', 'Backward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p2.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 5, 'anchorOffset'); + assert_equals(selection.focusNode, p1.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-wrap.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-wrap.html index 47d5c9d..515a59d08 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-wrap.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-backward-wrap.html
@@ -1,29 +1,31 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "ある。" and "名前はまだ" must be selected.</p> <div id="test" style="-webkit-writing-mode: vertical-rl; outline: none;" contenteditable> -<p>吾輩は猫である。名前はまだ無い。</p> +<p id="p1">吾輩は猫である。名前はまだ無い。</p> </div> - <span id="span-for-height-calc" style="-webkit-writing-mode: vertical-rl; outline: none;"> <p>吾輩は猫である。<br>名前はまだ無い。</p> </span> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var desiredHeight = document.getElementById('span-for-height-calc'); + var test = document.getElementById('test'); + test.style.height = (desiredHeight.offsetHeight + 2) + 'px'; + desiredHeight.style.display = 'none'; -var desiredHeight = document.getElementById('span-for-height-calc'); -var test = document.getElementById('test'); -test.style.height = (desiredHeight.offsetHeight + 2) + 'px'; -desiredHeight.style.display = 'none'; + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.firstChild, 13); + selection.modify('Extend', 'Backward', 'Line'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].firstChild, 13); -window.getSelection().modify('Extend', 'Backward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 13, 'anchorOffset'); + assert_equals(selection.focusNode, p1.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-br.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-br.html index c3e4b9d..b5406ac 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-br.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-br.html
@@ -1,21 +1,22 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "は猫である。" and "名前" must be selected.</p> <div id="test" style="height: 30ex; -webkit-writing-mode: vertical-rl; outline: none;" contenteditable> -<p>吾輩は猫である。<br>名前はまだ無い。</p> -</div> -<pre id="log"></pre> +<p id="p1">吾輩は猫である。<br>名前はまだ無い。</p> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.firstChild, 2); + selection.modify('Extend', 'Forward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].firstChild, 2); -window.getSelection().modify('Extend', 'Forward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 2, 'anchorOffset'); + assert_equals(selection.focusNode, p1.lastChild, 'focusNode'); + assert_equals(selection.focusOffset, 2, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-p.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-p.html index 1d45971b..0b73d14 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-p.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-p.html
@@ -1,22 +1,24 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "は猫である。" and "名前" must be selected.</p> <div id="test" style="height: 30ex; -webkit-writing-mode: vertical-rl; outline: none;" contenteditable> -<p>吾輩は猫である。</p> -<p>名前はまだ無い。</p> -</div> -<pre id="log"></pre> +<p id="p1">吾輩は猫である。</p> +<p id="p2">名前はまだ無い。</p> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + var p2 = document.getElementById('p2'); + selection.collapse(p1.firstChild, 2); + selection.modify('Extend', 'Forward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].firstChild, 2); -window.getSelection().modify('Extend', 'Forward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 2, 'anchorOffset'); + assert_equals(selection.focusNode, p2.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 2, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-wrap.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-wrap.html index 77abad4..dbd12f3 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-wrap.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-ltr-extend-line-forward-wrap.html
@@ -1,29 +1,32 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode. "は猫である。" and "名前" must be selected.</p> <div id="test" style="-webkit-writing-mode: vertical-rl; outline: none;" contenteditable> -<p>吾輩は猫である。名前はまだ無い。</p> +<p id="p1">吾輩は猫である。名前はまだ無い。</p> </div> <span id="span-for-height-calc" style="-webkit-writing-mode: vertical-rl; outline: none;"> <p>吾輩は猫である。<br>名前はまだ無い。</p> </span> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var desiredHeight = document.getElementById('span-for-height-calc'); + var test = document.getElementById('test'); + test.style.height = (desiredHeight.offsetHeight + 2) + 'px'; + desiredHeight.style.display = 'none'; -var desiredHeight = document.getElementById('span-for-height-calc'); -var test = document.getElementById('test'); -test.style.height = (desiredHeight.offsetHeight + 2) + 'px'; -desiredHeight.style.display = 'none'; + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.firstChild, 2); + selection.modify('Extend', 'Forward', 'Line'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].firstChild, 2); -window.getSelection().modify('Extend', 'Forward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 2, 'anchorOffset'); + assert_equals(selection.focusNode, p1.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 10, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-br.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-br.html index 73e8771b..ab47e94 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-br.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-br.html
@@ -1,21 +1,23 @@ -<!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode.</p> <div id="test" style="font-family: monospace; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl;-webkit-text-orientation:sideways-right;text-rendering:optimizeLegibility; outline: none;" contenteditable> -<p dir="rtl">אני חתול.<br>אין לי שם.</p> +<p id="p1" dir="rtl">אני חתול.<br>אין לי שם.</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.lastChild, 5); + selection.modify('Extend', 'Backward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].lastChild, 5); -window.getSelection().modify('Extend', 'Backward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.lastChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 5, 'anchorOffset'); + assert_equals(selection.focusNode, p1.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-p.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-p.html index 4f87284f..bc56bbb 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-p.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-backward-p.html
@@ -1,21 +1,24 @@ -<!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode.</p> <div id="test" style="font-family: monospace; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl;-webkit-text-orientation:sideways-right;text-rendering:optimizeLegibility; outline: none;" contenteditable> -<p dir="rtl">אני חתול.</p><p dir="rtl">אין לי שם.</p> +<p id="p1" dir="rtl">אני חתול.</p><p id="p2" dir="rtl">אין לי שם.</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + var p2 = document.getElementById('p2'); + selection.collapse(p2.firstChild, 5); + selection.modify('Extend', 'Backward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[1].lastChild, 5); -window.getSelection().modify('Extend', 'Backward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p2.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 5, 'anchorOffset'); + assert_equals(selection.focusNode, p1.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html index 6e755cf..3830f4a 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-br.html
@@ -1,21 +1,23 @@ <!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode.</p> <div id="test" style="font-family: monospace; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl; -webkit-text-orientation: sideways-right; outline: none;" contenteditable> -<p dir="rtl">אני חתול.<br>אין לי שם.</p> +<p id="p1" dir="rtl">אני חתול.<br>אין לי שם.</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.firstChild, 5); + selection.modify('Extend', 'Forward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].firstChild, 5); -window.getSelection().modify('Extend', 'Forward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 5, 'anchorOffset'); + assert_equals(selection.focusNode, p1.lastChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html index c3bbffe..494366b 100644 --- a/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html +++ b/third_party/WebKit/LayoutTests/editing/selection/vertical-rl-rtl-extend-line-forward-p.html
@@ -1,21 +1,23 @@ -<!DOCTYPE html> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<style> .selected { color: blue; } </style> -</head> -<body> +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <p>This tests horizontal caret movement in vertical writing mode.</p> <div id="test" style="font-family: monospace; font-size: 20px; height: 15ex; -webkit-writing-mode: vertical-rl;-webkit-text-orientation:sideways-right;text-rendering:optimizeLegibility; outline: none;" contenteditable> -<p dir="rtl">אני חתול.</p><p dir="rtl">אין לי שם.</p> +<p id="p1" dir="rtl">אני חתול.</p><p id="p2" dir="rtl">אין לי שם.</p> </div> -<pre id="log"></pre> +<div id="log"></div> <script> +test(function() { + var selection = window.getSelection(); + var p1 = document.getElementById('p1'); + selection.collapse(p1.firstChild, 5); + selection.modify('Extend', 'Forward', 'Line'); -var test = document.getElementById('test'); -window.getSelection().collapse(test.getElementsByTagName('p')[0].firstChild, 5); -window.getSelection().modify('Extend', 'Forward', 'Line'); - + assert_false(selection.isCollapsed, 'isCollapsed'); + assert_equals(selection.anchorNode, p1.firstChild, 'anchorNode'); + assert_equals(selection.anchorOffset, 5, 'anchorOffset'); + assert_equals(selection.focusNode, p2.firstChild, 'focusNode'); + assert_equals(selection.focusOffset, 5, 'focusOffset'); +}); </script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/painting-on-bad-canvas.html b/third_party/WebKit/LayoutTests/fast/canvas/painting-on-bad-canvas.html index 31c3805..8044178c 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/painting-on-bad-canvas.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/painting-on-bad-canvas.html
@@ -48,7 +48,7 @@ canvas.width = 0; testAPICalls(); -// Test a canvas so large that it has no chance of successfull allocating a backing +// Test a canvas so large that it has no chance of successful allocating a backing canvas.width = 10000000; canvas.height = 10000000; testAPICalls();
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-face-download-error.html b/third_party/WebKit/LayoutTests/fast/css/font-face-download-error.html index 0b722d0a..e78f0d1 100644 --- a/third_party/WebKit/LayoutTests/fast/css/font-face-download-error.html +++ b/third_party/WebKit/LayoutTests/fast/css/font-face-download-error.html
@@ -8,7 +8,7 @@ border: solid 1px; } -/* Test 0: Download sucess */ +/* Test 0: Download success */ @font-face { font-family:myfont_0; src: local('Courier'), local('Courier New');
diff --git a/third_party/WebKit/LayoutTests/fast/css/variables/custom-properties-in-object-model-expected.txt b/third_party/WebKit/LayoutTests/fast/css/variables/custom-properties-in-object-model-expected.txt new file mode 100644 index 0000000..8eca5ec --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/variables/custom-properties-in-object-model-expected.txt
@@ -0,0 +1,17 @@ +PASS style.getPropertyValue("--important") is "green" +PASS style.getPropertyValue("--not-important") is "red" +PASS style.getPropertyValue("color") is "var(--important)" +PASS style.getPropertyPriority("--important") is "important" +PASS style.getPropertyPriority("--not-important") is "" +PASS style.getPropertyValue("--foo") is "papayawhip" +PASS style.getPropertyPriority("--foo") is "" +PASS style.getPropertyPriority("--important-foo") is "important" +PASS style.getPropertyValue("--important-foo") is "" +PASS style.removeProperty("--foo") is "papayawhip" +PASS style.getPropertyValue("--foo") is "" +PASS computedStyle.setProperty("--error", "") threw exception NoModificationAllowedError: Failed to execute 'setProperty' on 'CSSStyleDeclaration': These styles are computed, and therefore the '--error' property is read-only.. +PASS cssText is "#test2 { --variable: value; }" +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/fast/css/variables/custom-properties-in-object-model.html b/third_party/WebKit/LayoutTests/fast/css/variables/custom-properties-in-object-model.html new file mode 100644 index 0000000..ab4ea32 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/variables/custom-properties-in-object-model.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<style> +#test { + --important:green!important; + --not-important:red; + color:var(--important); +} +#test2 { + --variable:value; +} +</style> +<div id="test"></div> +<script src="../../../resources/js-test.js"></script> +<script> +var style = document.styleSheets[0].rules[0].style; +shouldBeEqualToString('style.getPropertyValue("--important")', "green"); +shouldBeEqualToString('style.getPropertyValue("--not-important")', "red"); +shouldBeEqualToString('style.getPropertyValue("color")', "var(--important)"); +shouldBeEqualToString('style.getPropertyPriority("--important")', "important"); +shouldBeEqualToString('style.getPropertyPriority("--not-important")', ""); +style.setProperty("--foo", "papayawhip"); +style.setProperty("--important-foo", "navajowhite", "important"); +shouldBeEqualToString('style.getPropertyValue("--foo")', "papayawhip"); +shouldBeEqualToString('style.getPropertyPriority("--foo")', ""); +shouldBeEqualToString('style.getPropertyPriority("--important-foo")', "important"); +style.setProperty("--important-foo", "") +shouldBeEqualToString('style.getPropertyValue("--important-foo")', ""); +shouldBeEqualToString('style.removeProperty("--foo")', "papayawhip"); +shouldBeEqualToString('style.getPropertyValue("--foo")', ""); + +var computedStyle = window.getComputedStyle(document.getElementById("test")); +shouldThrow('computedStyle.setProperty("--error", "")', + '"NoModificationAllowedError: Failed to execute \'setProperty\' on \'CSSStyleDeclaration\': These styles are computed, and therefore the \'--error\' property is read-only."'); + +var cssText = document.styleSheets[0].rules[1].cssText; +shouldBeEqualToString('cssText', '#test2 { --variable: value; }') +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener-expected.txt index 0c0a5c2..b26ffb4 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener-expected.txt
@@ -3,10 +3,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS window.addEventListener("foo") is undefined -PASS window.removeEventListener("bar") is undefined -PASS window.addEventListener() is undefined -PASS window.removeEventListener() is undefined +PASS window.addEventListener("foo") threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. +PASS window.removeEventListener("bar") threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. +PASS window.addEventListener() threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. +PASS window.removeEventListener() threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener.html b/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener.html index 01b40fb..978b359 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener.html +++ b/third_party/WebKit/LayoutTests/fast/dom/Window/window-legacy-event-listener.html
@@ -7,11 +7,11 @@ <script> description("Test addEventListener() and removeEventListener() fail silently if arguments are missing."); -shouldBe('window.addEventListener("foo")', 'undefined'); -shouldBe('window.removeEventListener("bar")', 'undefined'); +shouldThrow('window.addEventListener("foo")'); +shouldThrow('window.removeEventListener("bar")'); -shouldBe('window.addEventListener()', 'undefined'); -shouldBe('window.removeEventListener()', 'undefined'); +shouldThrow('window.addEventListener()'); +shouldThrow('window.removeEventListener()'); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener-expected.txt index 6541ac3c..7ce3d86 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener-expected.txt
@@ -3,10 +3,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS new XMLHttpRequest().addEventListener("foo") is undefined -PASS new XMLHttpRequest().removeEventListener("bar") is undefined -PASS new XMLHttpRequest().addEventListener() is undefined -PASS new XMLHttpRequest().removeEventListener() is undefined +PASS new XMLHttpRequest().addEventListener("foo") threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. +PASS new XMLHttpRequest().removeEventListener("bar") threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. +PASS new XMLHttpRequest().addEventListener() threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. +PASS new XMLHttpRequest().removeEventListener() threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener.html b/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener.html index 5be2277..844a0266 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener.html +++ b/third_party/WebKit/LayoutTests/fast/dom/XMLHttpRequest-legacy-event-listener.html
@@ -7,11 +7,11 @@ <script> description("Test addEventListener() and removeEventListener() fail silently if arguments are missing."); -shouldBe('new XMLHttpRequest().addEventListener("foo")', 'undefined'); -shouldBe('new XMLHttpRequest().removeEventListener("bar")', 'undefined'); +shouldThrow('new XMLHttpRequest().addEventListener("foo")'); +shouldThrow('new XMLHttpRequest().removeEventListener("bar")'); -shouldBe('new XMLHttpRequest().addEventListener()', 'undefined'); -shouldBe('new XMLHttpRequest().removeEventListener()', 'undefined'); +shouldThrow('new XMLHttpRequest().addEventListener()'); +shouldThrow('new XMLHttpRequest().removeEventListener()'); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict-expected.txt index 17f558e097..ac62f33 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict-expected.txt
@@ -1,3 +1,3 @@ -This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in almost strict mode). If the test is sucessful, the text below should say "SUCCESS". +This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in almost strict mode). If the test is successful, the text below should say "SUCCESS". SUCCESS
diff --git a/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict.html b/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict.html index b7781e4..8479067 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict.html +++ b/third_party/WebKit/LayoutTests/fast/dom/compatMode-AlmostStrict.html
@@ -22,7 +22,7 @@ </script> </head> <body onload="runTests();"> -This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in almost strict mode). If the test is sucessful, the text below should say "SUCCESS". +This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in almost strict mode). If the test is successful, the text below should say "SUCCESS". <pre id="console"> </pre> </body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat-expected.txt index 7908452..543096a 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat-expected.txt
@@ -1,3 +1,3 @@ -This tests that compatMode returns 'BackCompat' when we are in quirk mode. If the test is sucessful, the text below should say "SUCCESS". +This tests that compatMode returns 'BackCompat' when we are in quirk mode. If the test is successful, the text below should say "SUCCESS". SUCCESS
diff --git a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat.html b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat.html index 4c8a629..3dd01744 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat.html +++ b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Compat.html
@@ -20,7 +20,7 @@ </script> </head> <body onload="runTests();"> -This tests that compatMode returns 'BackCompat' when we are in quirk mode. If the test is sucessful, the text below should say "SUCCESS". +This tests that compatMode returns 'BackCompat' when we are in quirk mode. If the test is successful, the text below should say "SUCCESS". <pre id="console"> </pre> </body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict-expected.txt index 6299855d..5c3be55 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict-expected.txt
@@ -1,3 +1,3 @@ -This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in strict mode). If the test is sucessful, the text below should say "SUCCESS". +This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in strict mode). If the test is successful, the text below should say "SUCCESS". SUCCESS
diff --git a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict.html b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict.html index 50855b5..685d787 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict.html +++ b/third_party/WebKit/LayoutTests/fast/dom/compatMode-Strict.html
@@ -22,7 +22,7 @@ </script> </head> <body onload="runTests();"> -This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in strict mode). If the test is sucessful, the text below should say "SUCCESS". +This tests that compatMode returns 'CSS1Compat' when the declared DTD is known (we are in strict mode). If the test is successful, the text below should say "SUCCESS". <pre id="console"> </pre> </body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments-expected.txt index 4a8a49a..8a0a16a4 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments-expected.txt
@@ -4,47 +4,35 @@ Signature: -void addEventListener(DOMString type, EventListener listener, optional boolean useCapture) -PASS internals.isUseCounted(document, AddEventListenerNoArguments) is false -PASS document.addEventListener() is undefined -PASS internals.isUseCounted(document, AddEventListenerNoArguments) is true -PASS internals.isUseCounted(document, AddEventListenerOneArgument) is false -PASS document.addEventListener("foo") is undefined -PASS internals.isUseCounted(document, AddEventListenerOneArgument) is true +void addEventListener(DOMString type, EventListener? listener, optional boolean useCapture) +PASS document.addEventListener() threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. +PASS document.addEventListener("foo") threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. PASS document.addEventListener("foo", listener) did not throw exception. PASS document.addEventListener("", listener) did not throw exception. PASS document.addEventListener("", function(){}) did not throw exception. PASS document.addEventListener("bar", listener, false) did not throw exception. PASS document.addEventListener("bar", listener, true) did not throw exception. -PASS document.addEventListener(null) is undefined PASS document.addEventListener(null, listener) did not throw exception. -PASS document.addEventListener("foo", null) is undefined +PASS document.addEventListener("foo", null) did not throw exception. PASS document.addEventListener("zork", listener, null) did not throw exception. -PASS document.addEventListener(undefined) is undefined -PASS document.addEventListener(undefined, listener) is undefined -PASS document.addEventListener("foo", undefined) is undefined +PASS document.addEventListener(undefined, listener) did not throw exception. +PASS document.addEventListener("foo", undefined) did not throw exception. PASS document.addEventListener("zork", listener, undefined) did not throw exception. Signature: -void removeEventListener(DOMString type, EventListener listener, optional boolean useCapture) -PASS internals.isUseCounted(document, RemoveEventListenerNoArguments) is false -PASS document.removeEventListener() is undefined -PASS internals.isUseCounted(document, RemoveEventListenerNoArguments) is true -PASS internals.isUseCounted(document, RemoveEventListenerOneArgument) is false -PASS document.removeEventListener("foo") is undefined -PASS internals.isUseCounted(document, RemoveEventListenerOneArgument) is true +void removeEventListener(DOMString type, EventListener? listener, optional boolean useCapture) +PASS document.removeEventListener() threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. +PASS document.removeEventListener("foo") threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. PASS document.removeEventListener("foo", listener) did not throw exception. PASS document.removeEventListener("foo", listener, true) did not throw exception. PASS document.removeEventListener("bar", listener, false) did not throw exception. PASS document.removeEventListener("bar", listener, false) did not throw exception. PASS document.removeEventListener("bar", listener, true) did not throw exception. -PASS document.removeEventListener(null) is undefined PASS document.removeEventListener(null, listener) did not throw exception. -PASS document.removeEventListener("foo", null) is undefined +PASS document.removeEventListener("foo", null) did not throw exception. PASS document.removeEventListener("zork", listener, null) did not throw exception. -PASS document.removeEventListener(undefined) is undefined -PASS document.removeEventListener(undefined, listener) is undefined -PASS document.removeEventListener("foo", undefined) is undefined +PASS document.removeEventListener(undefined, listener) did not throw exception. +PASS document.removeEventListener("foo", undefined) did not throw exception. PASS document.removeEventListener("zork", listener, undefined) did not throw exception. PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments.html b/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments.html index 4ed6589d..b7d8a80 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments.html +++ b/third_party/WebKit/LayoutTests/fast/dom/event-target-arguments.html
@@ -9,75 +9,39 @@ } debug('Signature:') -debug('void addEventListener(DOMString type, EventListener listener, optional boolean useCapture)'); -// FIXME: should throw on missing arguments: http://crbug.com/353484 -// shouldThrow('document.addEventListener()'); -// shouldThrow('document.addEventListener("foo")'); -var AddEventListenerNoArguments = 656; -shouldBeFalse('internals.isUseCounted(document, AddEventListenerNoArguments)'); -shouldBe('document.addEventListener()', 'undefined'); -shouldBeTrue('internals.isUseCounted(document, AddEventListenerNoArguments)'); -var AddEventListenerOneArgument = 657; -shouldBeFalse('internals.isUseCounted(document, AddEventListenerOneArgument)'); -shouldBe('document.addEventListener("foo")', 'undefined'); -shouldBeTrue('internals.isUseCounted(document, AddEventListenerOneArgument)'); +debug('void addEventListener(DOMString type, EventListener? listener, optional boolean useCapture)'); +shouldThrow('document.addEventListener()'); +shouldThrow('document.addEventListener("foo")'); shouldNotThrow('document.addEventListener("foo", listener)'); shouldNotThrow('document.addEventListener("", listener)'); shouldNotThrow('document.addEventListener("", function(){})'); shouldNotThrow('document.addEventListener("bar", listener, false)'); shouldNotThrow('document.addEventListener("bar", listener, true)'); // null -shouldBe('document.addEventListener(null)', 'undefined'); -shouldNotThrow('document.addEventListener(null, listener)'); // converted to "null" -// FIXME: throw on |null|: http://crbug.com/249598 -// shouldThrow('document.addEventListener("foo", null)'); -shouldBe('document.addEventListener("foo", null)', 'undefined'); +shouldNotThrow('document.addEventListener(null, listener)'); +shouldNotThrow('document.addEventListener("foo", null)'); shouldNotThrow('document.addEventListener("zork", listener, null)'); // undefined -// FIXME: behavior of undefined for mandatory arguments is unclear, but -// probably should throw -// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23532 -shouldBe('document.addEventListener(undefined)', 'undefined'); -// shouldThrow('document.addEventListener(undefined, listener)'); -// shouldThrow('document.addEventListener("foo", undefined)'); -shouldBe('document.addEventListener(undefined, listener)', 'undefined'); -shouldBe('document.addEventListener("foo", undefined)', 'undefined'); +shouldNotThrow('document.addEventListener(undefined, listener)'); +shouldNotThrow('document.addEventListener("foo", undefined)'); shouldNotThrow('document.addEventListener("zork", listener, undefined)'); debug(''); debug('Signature:'); -debug('void removeEventListener(DOMString type, EventListener listener, optional boolean useCapture)'); -// FIXME: should throw on missing arguments: http://crbug.com/353484 -// shouldThrow('document.removeEventListener()'); -// shouldThrow('document.removeEventListener("foo")'); -var RemoveEventListenerNoArguments = 658; -shouldBeFalse('internals.isUseCounted(document, RemoveEventListenerNoArguments)'); -shouldBe('document.removeEventListener()', 'undefined'); -shouldBeTrue('internals.isUseCounted(document, RemoveEventListenerNoArguments)'); -var RemoveEventListenerOneArgument = 659; -shouldBeFalse('internals.isUseCounted(document, RemoveEventListenerOneArgument)'); -shouldBe('document.removeEventListener("foo")', 'undefined'); -shouldBeTrue('internals.isUseCounted(document, RemoveEventListenerOneArgument)'); +debug('void removeEventListener(DOMString type, EventListener? listener, optional boolean useCapture)'); +shouldThrow('document.removeEventListener()'); +shouldThrow('document.removeEventListener("foo")'); shouldNotThrow('document.removeEventListener("foo", listener)'); shouldNotThrow('document.removeEventListener("foo", listener, true)'); shouldNotThrow('document.removeEventListener("bar", listener, false)'); shouldNotThrow('document.removeEventListener("bar", listener, false)'); shouldNotThrow('document.removeEventListener("bar", listener, true)'); // null -shouldBe('document.removeEventListener(null)', 'undefined'); -shouldNotThrow('document.removeEventListener(null, listener)'); // converted to "null" -// FIXME: throw on |null|: http://crbug.com/249598 -// shouldThrow('document.removeEventListener("foo", null)'); -shouldBe('document.removeEventListener("foo", null)', 'undefined'); +shouldNotThrow('document.removeEventListener(null, listener)'); +shouldNotThrow('document.removeEventListener("foo", null)'); shouldNotThrow('document.removeEventListener("zork", listener, null)'); // undefined -// FIXME: behavior of undefined for mandatory arguments is unclear, but -// probably should throw -// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23532 -shouldBe('document.removeEventListener(undefined)', 'undefined'); -// shouldthrow('document.removeeventlistener("foo", undefined)'); -// shouldthrow('document.removeeventlistener(undefined, listener)'); -shouldBe('document.removeEventListener(undefined, listener)', 'undefined'); -shouldBe('document.removeEventListener("foo", undefined)', 'undefined'); +shouldNotThrow('document.removeEventListener(undefined, listener)'); +shouldNotThrow('document.removeEventListener("foo", undefined)'); shouldNotThrow('document.removeEventListener("zork", listener, undefined)'); </script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener-expected.txt index dcb37d67..767a321 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener-expected.txt
@@ -3,10 +3,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS document.addEventListener("foo") is undefined -PASS document.removeEventListener("bar") is undefined -PASS document.addEventListener() is undefined -PASS document.removeEventListener() is undefined +PASS document.addEventListener("foo") threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. +PASS document.removeEventListener("bar") threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 1 present.. +PASS document.addEventListener() threw exception TypeError: Failed to execute 'addEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. +PASS document.removeEventListener() threw exception TypeError: Failed to execute 'removeEventListener' on 'EventTarget': 2 arguments required, but only 0 present.. PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener.html b/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener.html index a5b6eaf9..6686705 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener.html +++ b/third_party/WebKit/LayoutTests/fast/dom/node-legacy-event-listener.html
@@ -7,11 +7,11 @@ <script> description("Test addEventListener() and removeEventListener() fail silently if arguments are missing."); -shouldBe('document.addEventListener("foo")', 'undefined'); -shouldBe('document.removeEventListener("bar")', 'undefined'); +shouldThrow('document.addEventListener("foo")'); +shouldThrow('document.removeEventListener("bar")'); -shouldBe('document.addEventListener()', 'undefined'); -shouldBe('document.removeEventListener()', 'undefined'); +shouldThrow('document.addEventListener()'); +shouldThrow('document.removeEventListener()'); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/page-visibility-bubble-expected.txt b/third_party/WebKit/LayoutTests/fast/events/page-visibility-bubble-expected.txt new file mode 100644 index 0000000..06c04f42 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/page-visibility-bubble-expected.txt
@@ -0,0 +1,17 @@ +This test checks that 'visibilitychange' event bubbles. + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS document.visibilityState is "visible" +PASS document.hidden is false +PASS event.bubbles is true +PASS event.bubbles is true +PASS document.visibilityState is "hidden" +PASS document.hidden is true +PASS event.bubbles is true +PASS event.bubbles is true +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/fast/events/page-visibility-bubble.html b/third_party/WebKit/LayoutTests/fast/events/page-visibility-bubble.html new file mode 100644 index 0000000..6a486eb --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/page-visibility-bubble.html
@@ -0,0 +1,73 @@ +<html> +<body onload='startTest()'> + +<script src="../../resources/js-test.js"></script> + +<script> + +// 'visibilitychange' event should bubble as defined in http://www.w3.org/TR/page-visibility/#sec-processing-model +// See: http://crbug.com/501821 +description("This test checks that 'visibilitychange' event bubbles."); + +var jsTestIsAsync = true; + +function makePageVisible() { + if (window.testRunner) + testRunner.setPageVisibility("visible"); +} + +function makePageHidden() { + if (window.testRunner) + testRunner.setPageVisibility("hidden"); +} + +function checkIsPageVisible() { + shouldBeEqualToString("document.visibilityState", "visible"); + shouldBeFalse("document.hidden"); +} + +function checkIsPageHidden() { + shouldBeEqualToString("document.visibilityState", "hidden"); + shouldBeTrue("document.hidden"); +} + +// We will try to change the visibility states as: +// 0 - visible. (Initial - i.e. on load). +// 1 - hidden (should fire event and bubbles). +// 2 - visible (should fire event and bubbles). +var numVisibilityChanges = 0; + +function startTest() { + // Document listener will be fired first + document.addEventListener( + "visibilitychange", onVisibilityChangeDocument, false); + window.addEventListener( + "visibilitychange", onVisibilityChangeWindow, false); + checkIsPageVisible(); + numVisibilityChanges++; + makePageHidden(); +} + +function onVisibilityChangeDocument(event) { + shouldBeTrue("event.bubbles"); +} + +function onVisibilityChangeWindow(event) { + shouldBeTrue("event.bubbles"); + if (numVisibilityChanges == 1) { + numVisibilityChanges++; + checkIsPageHidden(); + makePageVisible(); + } else if (numVisibilityChanges == 2) { + finishJSTest(); + } else { + testFailed("Invalid number of visibility transitions"); + finishJSTest(); + } +} + +</script> + + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-tap-input-after-composition.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-tap-input-after-composition.html index 2dd4a1e..7c0ce705 100644 --- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-tap-input-after-composition.html +++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-tap-input-after-composition.html
@@ -6,7 +6,7 @@ <script> test(function(t) { - var sucessInput = false; + var successInput = false; if (!window.eventSender) return; var input = document.getElementById('input1'); @@ -18,7 +18,7 @@ var input2 = document.getElementById('input2'); input2.addEventListener('input', function () { - sucessInput = true; + successInput = true; }); var x = input2.offsetLeft + input2.offsetWidth / 2; var y = input2.offsetTop + input2.offsetHeight / 2; @@ -27,6 +27,6 @@ eventSender.gestureTap(x, y); eventSender.keyDown('a'); - assert_true(sucessInput); + assert_true(successInput); }, "This tests if the composition is reset before tapping of gesture."); -</script> \ No newline at end of file +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select/popup-menu-mouse-operations.html b/third_party/WebKit/LayoutTests/fast/forms/select/popup-menu-mouse-operations.html index 4e51120..22a3e23 100644 --- a/third_party/WebKit/LayoutTests/fast/forms/select/popup-menu-mouse-operations.html +++ b/third_party/WebKit/LayoutTests/fast/forms/select/popup-menu-mouse-operations.html
@@ -11,8 +11,32 @@ <option selected>bar</option> <option>baz</option> </select> +<select id="menu2" style="font-size:13px; font-family:Arial"> + <option>option1</option> + <option>option2</option> + <option>option3</option> + <option>option4</option> + <option>option5</option> + <option>option6</option> + <option>option7</option> + <option>option8</option> + <option>option9</option> + <option>option10</option> + <option>option11</option> + <option>option12</option> + <option>option13</option> + <option>option14</option> + <option>option15</option> + <option>option16</option> + <option>option17</option> + <option>option18</option> + <option>option19</option> + <option>option20</option> + <option>option21</option> +</select> <script> var menuElement = document.getElementById('menu'); +var menuElement2 = document.getElementById('menu2'); var picker = null; var clickEventCounter = 0; menuElement.addEventListener('click', function() { clickEventCounter++; }, false); @@ -84,6 +108,18 @@ shouldBeEqualToString('menu.value', 'bar'); shouldBeEqualToString('internals.selectMenuListText(menu)', 'bar'); + waitUntilClosing(function() { + openPicker(menu2, test3, openPickerErrorCallback); + }); +} + +function test3() { + picker = window.internals.pagePopupWindow.global.picker; + // We had a bug that almost-invisible OPTION was selected and the popup was + // scrolled. crbug.com/558287. + eventSender.mouseMoveTo(10, picker._selectElement.offsetHeight - 2); + shouldBeEqualToString('picker._selectElement.selectedOptions[0].label', 'option20'); + finishJSTest(); }
diff --git a/third_party/WebKit/LayoutTests/fast/js/exception-thrown-from-new-expected.txt b/third_party/WebKit/LayoutTests/fast/js/exception-thrown-from-new-expected.txt deleted file mode 100644 index a272b45..0000000 --- a/third_party/WebKit/LayoutTests/fast/js/exception-thrown-from-new-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This page tests exceptions thrown from 'new' expressions. If the test passes, you'll see a series of PASS messages below. - -FAIL: e1 should be 'TypeError: 'undefined' is not a constructor (evaluating 'new f')' but instead is 'TypeError: f is not a function'. -FAIL: e2 should be 'TypeError: 'undefined' is not a function (evaluating 'g()')' but instead is 'TypeError: g is not a function'. -
diff --git a/third_party/WebKit/LayoutTests/fast/js/exception-thrown-from-new.html b/third_party/WebKit/LayoutTests/fast/js/exception-thrown-from-new.html deleted file mode 100644 index 9924051..0000000 --- a/third_party/WebKit/LayoutTests/fast/js/exception-thrown-from-new.html +++ /dev/null
@@ -1,44 +0,0 @@ -<p> -This page tests exceptions thrown from 'new' expressions. If the test passes, -you'll see a series of PASS messages below. -</p> -<pre id="console"></pre> - -<script> -function log(s) -{ - document.getElementById("console").appendChild(document.createTextNode(s + "\n")); -} - -function shouldBe(a, aDescription, b) -{ - if (a == b) { - log("PASS: " + aDescription + " should be '" + String(b) + "' and is."); - return; - } - - log ("FAIL: " + aDescription + " should be '" + String(b) + "' but instead is '" + String(a) + "'."); -} - -if (window.testRunner) - testRunner.dumpAsText(); - -(function () { - try { - var f; - new f; - } catch(e1) { - shouldBe(e1, "e1", "TypeError: 'undefined' is not a constructor (evaluating 'new f')"); - } -})(); - -(function () { - try { - var f; - var g; - new f(g()); - } catch(e2) { - shouldBe(e2, "e2", "TypeError: 'undefined' is not a function (evaluating 'g()')"); - } -})(); -</script>
diff --git a/third_party/WebKit/LayoutTests/fast/js/function-length-expected.txt b/third_party/WebKit/LayoutTests/fast/js/function-length-expected.txt index e5c46dc..1e2b7fb0 100644 --- a/third_party/WebKit/LayoutTests/fast/js/function-length-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/js/function-length-expected.txt
@@ -7,7 +7,8 @@ PASS window.open.length is 2 PASS window.setTimeout.length is 1 PASS window.clearTimeout.length is 0 -PASS window.addEventListener.length is 0 +PASS window.addEventListener.length is 2 +PASS window.removeEventListener.length is 2 PASS window.postMessage.length is 2 PASS window.dispatchEvent.length is 1 PASS window.openDatabase.length is 4
diff --git a/third_party/WebKit/LayoutTests/fast/js/function-length.html b/third_party/WebKit/LayoutTests/fast/js/function-length.html index e95219b1..147d5ab 100644 --- a/third_party/WebKit/LayoutTests/fast/js/function-length.html +++ b/third_party/WebKit/LayoutTests/fast/js/function-length.html
@@ -11,9 +11,8 @@ shouldBe('window.open.length', '2'); shouldBe('window.setTimeout.length', '1'); shouldBe('window.clearTimeout.length', '0'); -// addEventListener.length should be 2, but legacy content calls with 0 or 1 -// argument. See http://crbug.com/249598 -shouldBe('window.addEventListener.length', '0'); +shouldBe('window.addEventListener.length', '2'); +shouldBe('window.removeEventListener.length', '2'); shouldBe('window.postMessage.length', '2'); shouldBe('window.dispatchEvent.length', '1'); shouldBe('window.openDatabase.length', '4');
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/balance-break-inside-avoid-expected.txt b/third_party/WebKit/LayoutTests/fast/multicol/balance-break-inside-avoid-expected.txt new file mode 100644 index 0000000..3ed4ddf --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/balance-break-inside-avoid-expected.txt
@@ -0,0 +1,3 @@ +There should be a blue square below. + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/balance-break-inside-avoid.html b/third_party/WebKit/LayoutTests/fast/multicol/balance-break-inside-avoid.html new file mode 100644 index 0000000..fd167d3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/multicol/balance-break-inside-avoid.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<script src="../../resources/check-layout.js"></script> +<style> + .multicol { -webkit-columns:2; -webkit-column-gap:0; position:relative; width:200px; background:blue; } + .multicol * { -webkit-column-break-inside:avoid; height:100px; background:white; } +</style> +<p>There should be a blue square below.</p> +<div class="multicol" data-expected-height="200"> + <div data-offset-x="0" data-offset-y="0"></div> + <div data-offset-x="0" data-offset-y="100"></div> + <div data-offset-x="100" data-offset-y="0"></div> +</div> +<script> + checkLayout(".multicol"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/destroy-scrollbar-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/destroy-scrollbar-expected.txt index 9ae8990..011d03c 100644 --- a/third_party/WebKit/LayoutTests/fast/repaint/destroy-scrollbar-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/repaint/destroy-scrollbar-expected.txt
@@ -6,10 +6,12 @@ "contentsOpaque": true, "drawsContent": true, "repaintRects": [ - [185, 100, 15, 200] + [185, 100, 15, 200], + [0, 100, 200, 200] ], "paintInvalidationClients": [ "VerticalScrollbar", + "LayoutBlockFlow (positioned) DIV", "LayoutBlockFlow (positioned) DIV" ] }
diff --git a/third_party/WebKit/LayoutTests/fast/text/bidi-reverse-runs-crash-expected.txt b/third_party/WebKit/LayoutTests/fast/text/bidi-reverse-runs-crash-expected.txt index 43c5887..1434c039 100644 --- a/third_party/WebKit/LayoutTests/fast/text/bidi-reverse-runs-crash-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/text/bidi-reverse-runs-crash-expected.txt
@@ -1,2 +1,2 @@ - +sdf PASS if did not crash.
diff --git a/third_party/WebKit/LayoutTests/fast/text/international/iso-8859-8-and-isolate-expected.html b/third_party/WebKit/LayoutTests/fast/text/international/iso-8859-8-and-isolate-expected.html new file mode 100644 index 0000000..4e03a25 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/international/iso-8859-8-and-isolate-expected.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<meta charset="ISO-8859-8"> +<style> +li { + font-size: 50px; + margin-left:1em; +} +</style> +<p>All lines must start with "â" and end with "ë". +<ol> + <li>â÷ë + <li>â÷ë + <li>â÷ë + <li>â÷ë + <li>â÷ë + <li>â÷ë +</ol>
diff --git a/third_party/WebKit/LayoutTests/fast/text/international/iso-8859-8-and-isolate.html b/third_party/WebKit/LayoutTests/fast/text/international/iso-8859-8-and-isolate.html new file mode 100644 index 0000000..755c91f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/international/iso-8859-8-and-isolate.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="ISO-8859-8"> +<style> +li { + font-size: 50px; + margin-left:1em; +} +.isolate { + unicode-bidi: -moz-isolate; + unicode-bidi: -ms-isolate; + unicode-bidi: -webkit-isolate; + unicode-bidi: isolate; +} +</style> +<p>All lines must start with "â" and end with "ë". +<ol> + <li>â÷ë + <li><span dir=ltr>â÷ë + <li><span dir=rtl>â÷ë + <li><span class=isolate>â÷ë + <li><span class=isolate dir=ltr>â÷ë + <li><span class=isolate dir=rtl>â÷ë +</ol>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webfont/font-display-expected.html b/third_party/WebKit/LayoutTests/http/tests/webfont/font-display-expected.html new file mode 100644 index 0000000..b61799f --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/webfont/font-display-expected.html
@@ -0,0 +1,86 @@ +<!DOCTYPE html> +<title>Test for font-display @font-face descriptor</title> +<script src="/js-test-resources/ahem.js"></script> +<style> +.ahem { + font-family: Ahem; +} +.arial { + font-family: Arial; +} +</style> +<p>Tests how text with a font that takes <i>delay</i> seconds to load look like after <i>T</i> seconds from load start.</p> +<table> +<tr> + <th>T[sec]</th> + <th>delay[sec]</th> + <th>auto</th> + <th>block</th> + <th>swap</th> + <th>fallback</th> + <th>optional</th> +</tr> +<tr> + <td>0</td> + <td>1</td> + <td></td> + <td></td> + <td class="arial">a</td> + <td></td> + <td></td> +</tr> +<tr> + <td>1</td> + <td>0</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> +</tr> +<tr> + <td>1</td> + <td>0.5</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="arial">a</td> +</tr> +<tr> + <td>1</td> + <td>3</td> + <td></td> + <td></td> + <td class="arial">a</td> + <td class="arial">a</td> + <td class="arial">a</td> +</tr> +<tr> + <td>5</td> + <td>2</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="arial">a</td> +</tr> +<tr> + <td>5</td> + <td>4</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="ahem">a</td> + <td class="arial">a</td> + <td class="arial">a</td> +</tr> +<tr> + <td>5</td> + <td>8</td> + <td class="arial">a</td> + <td class="arial">a</td> + <td class="arial">a</td> + <td class="arial">a</td> + <td class="arial">a</td> +</tr> +</table>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webfont/font-display.html b/third_party/WebKit/LayoutTests/http/tests/webfont/font-display.html new file mode 100644 index 0000000..0945242 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/webfont/font-display.html
@@ -0,0 +1,67 @@ +<!DOCTYPE html> +<title>Test for font-display @font-face descriptor</title> +<style> +.hidden { display: none; } +</style> +<p>Tests how text with a font that takes <i>delay</i> seconds to load look like after <i>T</i> seconds from load start.</p> +<table id="container"> + <tr> + <th>T[sec]</th> + <th>delay[sec]</th> + <th>auto</th> + <th>block</th> + <th>swap</th> + <th>fallback</th> + <th>optional</th> + </tr> +</table> +<script> +if (window.testRunner) + testRunner.waitUntilDone(); + +var fontDisplayValues = ['auto', 'block', 'swap', 'fallback', 'optional']; +var configs = [{time: 0, delay: 1000}, + {time: 1000, delay: 0}, + {time: 1000, delay: 500}, + {time: 1000, delay: 3000}, + {time: 5000, delay: 2000}, + {time: 5000, delay: 4000}, + {time: 5000, delay: 8000}]; + +function makeFontFaceDeclaration(family, config, display) { + var url = '/resources/Ahem.ttf'; + if (config.delay > 0) + url = 'slow-ahem-loading.cgi?delay=' + config.delay + '&t=' + config.time; + return '@font-face { font-family: ' + family + '; src: url(' + url + '); font-display: ' + display + '; }'; +} + + +var maxTime = Math.max.apply(null, configs.map((config) => config.time)); +var table = document.getElementById('container'); + +for (var config, i = 0; config = configs[i]; i++) { + var tr = document.createElement('tr'); + tr.classList.add('hidden'); + var td1 = document.createElement('td'); + td1.textContent = config.time / 1000; + tr.appendChild(td1); + var td2 = document.createElement('td'); + td2.textContent = config.delay / 1000; + tr.appendChild(td2); + + for (var display, j = 0; display = fontDisplayValues[j]; j++) { + var family = [display, config.time, config.delay].join('-'); + var rule = makeFontFaceDeclaration(family, config, display); + document.styleSheets[0].insertRule(rule, 0); + var td = document.createElement('td'); + td.textContent = 'a'; + td.style.fontFamily = family + ', Arial'; + tr.appendChild(td); + } + table.appendChild(tr); + setTimeout((function(tr){tr.classList.remove('hidden')}).bind(null, tr), maxTime - config.time); +} + +if (window.testRunner) + setTimeout(function() { testRunner.notifyDone(); }, maxTime); +</script>
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt index 15ba330..4031ea1 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/console/console-object-preview-expected.txt
@@ -36,22 +36,22 @@ console-object-preview.html:20 [0, 0, 1] console-message-text source-code > console-message-url webkit-html-resource-link > object-value-array source-code > console-object-preview > object-value-number > object-value-number > object-value-number console-object-preview.html:20 [0, 0, 2] console-message-text source-code > console-message-url webkit-html-resource-link > object-value-array source-code > console-object-preview > object-value-number > object-value-number > object-value-number console-object-preview.html:23 Object with many properties console-message-text source-code > console-message-url webkit-html-resource-link -console-object-preview.html:28 Object {property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-info-state-note > children +console-object-preview.html:28 Object {property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-info-state-note > children console-object-preview.html:30 Array with many properties console-message-text source-code > console-message-url webkit-html-resource-link -console-object-preview.html:35 [0, 1, property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…] console-message-text source-code > console-message-url webkit-html-resource-link > object-value-array source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent > selection fill > console-object-preview > object-value-number > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-info-state-note > children +console-object-preview.html:35 [0, 1, property_0: 0, property_1: 1, property_2: 2, property_3: 3, property_4: 4…] console-message-text source-code > console-message-url webkit-html-resource-link > object-value-array source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > object-info-state-note > children console-object-preview.html:37 Object with proto console-message-text source-code > console-message-url webkit-html-resource-link -console-object-preview.html:40 Object {d: 1} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent > selection fill > console-object-preview > name > object-value-number > object-info-state-note > children +console-object-preview.html:40 Object {d: 1} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-number > object-info-state-note > children console-object-preview.html:42 Sparse array console-message-text source-code > console-message-url webkit-html-resource-link console-object-preview.html:45 [50: 50] console-message-text source-code > console-message-url webkit-html-resource-link > object-value-array source-code > console-object-preview > name > object-value-number console-object-preview.html:47 Dense array with indexes and propeties console-message-text source-code > console-message-url webkit-html-resource-link -console-object-preview.html:53 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99…] console-message-text source-code > console-message-url webkit-html-resource-link > object-value-array source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-info-state-note > children +console-object-preview.html:53 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99…] console-message-text source-code > console-message-url webkit-html-resource-link > object-value-array source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-value-number > object-info-state-note > children console-object-preview.html:55 Object with properties containing whitespaces console-message-text source-code > console-message-url webkit-html-resource-link console-object-preview.html:62 Object {" a b ": " a b ", c d: "c d", "": "", " ": " ", "a↵↵b↵c": "a↵↵b↵c"} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-object-preview > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string > name > object-value-string console-object-preview.html:64 Object with a document.all property console-message-text source-code > console-message-url webkit-html-resource-link -console-object-preview.html:65 Object {all: HTMLAllCollection[7]} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent > selection fill > console-object-preview > name > object-value-array > object-info-state-note > children +console-object-preview.html:65 Object {all: HTMLAllCollection[7]} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-array > object-info-state-note > children console-object-preview.html:67 Object with special numbers console-message-text source-code > console-message-url webkit-html-resource-link console-object-preview.html:69 Object {nan: NaN, posInf: Infinity, negInf: -Infinity, negZero: -0} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number console-object-preview.html:71 Object with exactly 5 properties: expected to be lossless console-message-text source-code > console-message-url webkit-html-resource-link console-object-preview.html:72 Object {a: 1, b: 2, c: 3, d: 4, e: 5} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-object-preview > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number > name > object-value-number -console-object-preview.html:74 Object {null: null, undef: undefined, regexp: /^[regexp]$/g, bool: false} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent > selection fill > console-object-preview > name > object-value-null > name > object-value-undefined > name > object-value-regexp > name > object-value-boolean > object-info-state-note > children +console-object-preview.html:74 Object {null: null, undef: undefined, regexp: /^[regexp]$/g, bool: false} console-message-text source-code > console-message-url webkit-html-resource-link > object-value-object source-code > console-view-object-properties-section > tree-outline source-code object-properties-section > parent object-properties-section-root-element > selection fill > console-object-preview > name > object-value-null > name > object-value-undefined > name > object-value-regexp > name > object-value-boolean > object-info-state-note > children
diff --git a/third_party/WebKit/LayoutTests/inspector/layers/layer-canvas-log-expected.txt b/third_party/WebKit/LayoutTests/inspector/layers/layer-canvas-log-expected.txt index 4ff3282..cf83f08 100644 --- a/third_party/WebKit/LayoutTests/inspector/layers/layer-canvas-log-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/layers/layer-canvas-log-expected.txt
@@ -113,19 +113,10 @@ method : "save" } 6 : { - method : "setMatrix" + method : "translate" params : { - matrix : [ - 1 - 0 - 0 - 0 - 1 - 71 - 0 - 0 - 1 - ] + dx : 0 + dy : 71 } } 7 : {
diff --git a/third_party/WebKit/LayoutTests/jquery/resources/test/unit/ajax.js b/third_party/WebKit/LayoutTests/jquery/resources/test/unit/ajax.js index 2a2ac46..393fae7 100644 --- a/third_party/WebKit/LayoutTests/jquery/resources/test/unit/ajax.js +++ b/third_party/WebKit/LayoutTests/jquery/resources/test/unit/ajax.js
@@ -1015,7 +1015,7 @@ test("synchronous request with callbacks", function() { expect(2); var result; - jQuery.ajax({url: url("data/json_obj.js"), async: false, dataType: "text", success: function(data) { ok(true, "sucess callback executed"); result = data; } }); + jQuery.ajax({url: url("data/json_obj.js"), async: false, dataType: "text", success: function(data) { ok(true, "success callback executed"); result = data; } }); ok( /^{ "data"/.test( result ), "check returned text" ); }); @@ -2249,4 +2249,4 @@ } -//} \ No newline at end of file +//}
diff --git a/third_party/WebKit/LayoutTests/platform/android/inspector/layers/layer-canvas-log-expected.txt b/third_party/WebKit/LayoutTests/platform/android/inspector/layers/layer-canvas-log-expected.txt new file mode 100644 index 0000000..4ff3282 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/inspector/layers/layer-canvas-log-expected.txt
@@ -0,0 +1,165 @@ + +Canvas log: +{ + 0 : { + method : "drawRect" + params : { + paint : { + color : "#FF0000FF" + filterLevel : "Low" + flags : "AntiAlias" + hinting : "Normal" + strokeCap : "Butt" + strokeJoin : "Miter" + strokeMiter : 4 + strokeWidth : 0 + styleName : "Fill" + textAlign : "Left" + textEncoding : "UTF-8" + textScaleX : 1 + textSize : 12 + textSkewX : 0 + } + rect : { + bottom : 100 + left : 0 + right : 100 + top : 0 + } + } + } + 1 : { + method : "drawRect" + params : { + paint : { + color : "#FFFF0000" + filterLevel : "Low" + flags : "AntiAlias" + hinting : "Normal" + strokeCap : "Butt" + strokeJoin : "Miter" + strokeMiter : 4 + strokeWidth : 0 + styleName : "Fill" + textAlign : "Left" + textEncoding : "UTF-8" + textScaleX : 1 + textSize : 12 + textSkewX : 0 + } + rect : { + bottom : 50 + left : 0 + right : 50 + top : 0 + } + } + } + 2 : { + method : "drawImageRect" + params : { + dst : { + bottom : 71 + left : 0 + right : 19 + top : 50 + } + image : { + height : 21 + opaque : false + width : 19 + } + paint : { + color : "#FF000000" + filterLevel : "High" + flags : "AntiAlias" + hinting : "Normal" + strokeCap : "Butt" + strokeJoin : "Miter" + strokeMiter : 4 + strokeWidth : 0 + styleName : "Fill" + textAlign : "Left" + textEncoding : "UTF-8" + textScaleX : 1 + textSize : 12 + textSkewX : 0 + } + src : { + bottom : 21 + left : 0 + right : 19 + top : 0 + } + } + } + 3 : { + method : "save" + } + 4 : { + method : "clipRect" + params : { + SkRegion::Op : "kIntersect_Op" + rect : { + bottom : 221 + left : 0 + right : 300 + top : 71 + } + softClipEdgeStyle : false + } + } + 5 : { + method : "save" + } + 6 : { + method : "setMatrix" + params : { + matrix : [ + 1 + 0 + 0 + 0 + 1 + 71 + 0 + 0 + 1 + ] + } + } + 7 : { + method : "drawRect" + params : { + paint : { + color : "#7F000000" + filterLevel : "Low" + flags : "AntiAlias" + hinting : "Normal" + strokeCap : "Butt" + strokeJoin : "Miter" + strokeMiter : 4 + strokeWidth : 0 + styleName : "Fill" + textAlign : "Left" + textEncoding : "UTF-8" + textScaleX : 1 + textSize : 12 + textSkewX : 0 + } + rect : { + bottom : 10 + left : 0 + right : 10 + top : 0 + } + } + } + 8 : { + method : "restore" + } + 9 : { + method : "restore" + } +} +
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index bfb7c44..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index ed4b520..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,128) size 19x0 - LayoutText {#text} at (20,0) size 19x128 - text run at (20,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index c7a6520..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 3809b7b..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,128) size 19x0 - LayoutText {#text} at (20,0) size 19x128 - text run at (20,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index 3e46303..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index ed4b520..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,128) size 19x0 - LayoutText {#text} at (20,0) size 19x128 - text run at (20,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png deleted file mode 100644 index ebc17a0..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt deleted file mode 100644 index 6740c31..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 88x210 - LayoutBlockFlow {P} at (16,0) size 20x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (52,0) size 20x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png deleted file mode 100644 index 3e46303..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt deleted file mode 100644 index 12fbb162..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x195 - LayoutBlockFlow {HTML} at (0,0) size 800x195 - LayoutBlockFlow {BODY} at (8,16) size 784x166 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x130 - LayoutBlockFlow {P} at (16,0) size 40x130 - LayoutText {#text} at (0,0) size 39x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (20,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,179) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 13 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index df224ff..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 3809b7b..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,128) size 19x0 - LayoutText {#text} at (20,0) size 19x128 - text run at (20,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png deleted file mode 100644 index 9701ec0..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt deleted file mode 100644 index 6906688..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 88x210 - LayoutBlockFlow {P} at (16,0) size 20x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (52,0) size 20x210 - LayoutText {#text} at (0,0) size 19x128 - text run at (0,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png deleted file mode 100644 index df224ff..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt deleted file mode 100644 index a321822..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x195 - LayoutBlockFlow {HTML} at (0,0) size 800x195 - LayoutBlockFlow {BODY} at (8,16) size 784x166 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 655x19 - text run at (0,0) width 655: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x130 - LayoutBlockFlow {P} at (16,0) size 40x130 - LayoutText {#text} at (0,0) size 39x128 - text run at (0,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (20,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,179) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 10 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png deleted file mode 100644 index 4843f09a..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt deleted file mode 100644 index 65b77f9..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 84x135 - LayoutBlockFlow {P} at (20,0) size 44x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (0,27) size 22x0 - LayoutText {#text} at (22,15) size 22x120 - text run at (22,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png deleted file mode 100644 index 930fd28..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt deleted file mode 100644 index 207c2f0c..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 104x135 - LayoutBlockFlow {P} at (20,0) size 22x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (62,0) size 22x135 - LayoutText {#text} at (0,15) size 22x120 - text run at (0,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png deleted file mode 100644 index 4843f09a..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt deleted file mode 100644 index 65b77f9..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 84x135 - LayoutBlockFlow {P} at (20,0) size 44x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (0,27) size 22x0 - LayoutText {#text} at (22,15) size 22x120 - text run at (22,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png deleted file mode 100644 index 930fd28..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt deleted file mode 100644 index 207c2f0c..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 104x135 - LayoutBlockFlow {P} at (20,0) size 22x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (62,0) size 22x135 - LayoutText {#text} at (0,15) size 22x120 - text run at (0,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index a2d380b..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 3d82e72..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x284 - LayoutBlockFlow {HTML} at (0,0) size 800x284.39 - LayoutBlockFlow {BODY} at (8,16) size 784x255.39 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 80x215.39 - LayoutBlockFlow {P} at (16,0) size 48x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (3,128) size 18x0 - LayoutText {#text} at (27,0) size 18x128 - text run at (27,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,268.39) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index b6b5e31d..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 34827873..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x284 - LayoutBlockFlow {HTML} at (0,0) size 800x284.39 - LayoutBlockFlow {BODY} at (8,16) size 784x255.39 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 80x215.39 - LayoutBlockFlow {P} at (16,0) size 48x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (3,128) size 18x0 - LayoutText {#text} at (27,0) size 18x128 - text run at (27,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,268.39) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index e891f7e..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 3d82e72..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x284 - LayoutBlockFlow {HTML} at (0,0) size 800x284.39 - LayoutBlockFlow {BODY} at (8,16) size 784x255.39 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 80x215.39 - LayoutBlockFlow {P} at (16,0) size 48x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (3,128) size 18x0 - LayoutText {#text} at (27,0) size 18x128 - text run at (27,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,268.39) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png deleted file mode 100644 index b65603af..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt deleted file mode 100644 index 00ef397d..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x284 - LayoutBlockFlow {HTML} at (0,0) size 800x284.39 - LayoutBlockFlow {BODY} at (8,16) size 784x255.39 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 96x215.39 - LayoutBlockFlow {P} at (16,0) size 24x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (56,0) size 24x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,268.39) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png deleted file mode 100644 index e891f7e..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt deleted file mode 100644 index 5d10127..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x199 - LayoutBlockFlow {HTML} at (0,0) size 800x199 - LayoutBlockFlow {BODY} at (8,16) size 784x170 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 80x130 - LayoutBlockFlow {P} at (16,0) size 48x130 - LayoutText {#text} at (3,0) size 42x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (27,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,183) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 13 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index ba3c6553..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 34827873..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x284 - LayoutBlockFlow {HTML} at (0,0) size 800x284.39 - LayoutBlockFlow {BODY} at (8,16) size 784x255.39 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 80x215.39 - LayoutBlockFlow {P} at (16,0) size 48x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (3,128) size 18x0 - LayoutText {#text} at (27,0) size 18x128 - text run at (27,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,268.39) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png deleted file mode 100644 index 7f498a6..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt deleted file mode 100644 index e2abeec2..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x284 - LayoutBlockFlow {HTML} at (0,0) size 800x284.39 - LayoutBlockFlow {BODY} at (8,16) size 784x255.39 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 96x215.39 - LayoutBlockFlow {P} at (16,0) size 24x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (56,0) size 24x215.39 - LayoutText {#text} at (3,0) size 18x128 - text run at (3,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,268.39) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png deleted file mode 100644 index ba3c6553..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt deleted file mode 100644 index b240c066..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x199 - LayoutBlockFlow {HTML} at (0,0) size 800x199 - LayoutBlockFlow {BODY} at (8,16) size 784x170 - LayoutBlockFlow {P} at (0,0) size 784x24 - LayoutText {#text} at (0,4) size 702x18 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,40) size 80x130 - LayoutBlockFlow {P} at (16,0) size 48x130 - LayoutText {#text} at (3,0) size 42x128 - text run at (3,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (27,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,183) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 10 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index b1354ff..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 65419919..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x282 - LayoutBlockFlow {HTML} at (0,0) size 800x282.39 - LayoutBlockFlow {BODY} at (8,16) size 784x253.39 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 76x215.39 - LayoutBlockFlow {P} at (16,0) size 44x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (2,128) size 18x0 - LayoutText {#text} at (24,0) size 18x128 - text run at (24,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,266.39) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index 11e6b8b..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 99dd0ac6..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x282 - LayoutBlockFlow {HTML} at (0,0) size 800x282.39 - LayoutBlockFlow {BODY} at (8,16) size 784x253.39 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 76x215.39 - LayoutBlockFlow {P} at (16,0) size 44x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (2,128) size 18x0 - LayoutText {#text} at (24,0) size 18x128 - text run at (24,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,266.39) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index afbf1b3..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 65419919..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x282 - LayoutBlockFlow {HTML} at (0,0) size 800x282.39 - LayoutBlockFlow {BODY} at (8,16) size 784x253.39 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 76x215.39 - LayoutBlockFlow {P} at (16,0) size 44x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (2,128) size 18x0 - LayoutText {#text} at (24,0) size 18x128 - text run at (24,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,266.39) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png deleted file mode 100644 index 8b9f430..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt deleted file mode 100644 index 8cc6aa66a..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x282 - LayoutBlockFlow {HTML} at (0,0) size 800x282.39 - LayoutBlockFlow {BODY} at (8,16) size 784x253.39 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 92x215.39 - LayoutBlockFlow {P} at (16,0) size 22x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (54,0) size 22x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,266.39) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png deleted file mode 100644 index afbf1b3..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt deleted file mode 100644 index a4f65f43..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x197 - LayoutBlockFlow {HTML} at (0,0) size 800x197 - LayoutBlockFlow {BODY} at (8,16) size 784x168 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 76x130 - LayoutBlockFlow {P} at (16,0) size 44x130 - LayoutText {#text} at (2,0) size 40x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (24,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,181) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 13 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index fdfaf38b..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 99dd0ac6..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x282 - LayoutBlockFlow {HTML} at (0,0) size 800x282.39 - LayoutBlockFlow {BODY} at (8,16) size 784x253.39 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 76x215.39 - LayoutBlockFlow {P} at (16,0) size 44x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (2,128) size 18x0 - LayoutText {#text} at (24,0) size 18x128 - text run at (24,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,266.39) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png deleted file mode 100644 index fb2df88..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt deleted file mode 100644 index 60e91b01..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x282 - LayoutBlockFlow {HTML} at (0,0) size 800x282.39 - LayoutBlockFlow {BODY} at (8,16) size 784x253.39 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 92x215.39 - LayoutBlockFlow {P} at (16,0) size 22x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (54,0) size 22x215.39 - LayoutText {#text} at (2,0) size 18x128 - text run at (2,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,266.39) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png deleted file mode 100644 index fdfaf38b..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt deleted file mode 100644 index f0eeaf0..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x197 - LayoutBlockFlow {HTML} at (0,0) size 800x197 - LayoutBlockFlow {BODY} at (8,16) size 784x168 - LayoutBlockFlow {P} at (0,0) size 784x22 - LayoutText {#text} at (0,3) size 702x18 - text run at (0,3) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,38) size 76x130 - LayoutBlockFlow {P} at (16,0) size 44x130 - LayoutText {#text} at (2,0) size 40x128 - text run at (2,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (24,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,181) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 10 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png deleted file mode 100644 index 53befd2c..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt deleted file mode 100644 index 978aed7..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x198 - LayoutBlockFlow {HTML} at (0,0) size 800x198.34 - LayoutBlockFlow {BODY} at (8,16) size 784x169.34 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x18 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 88x135.34 - LayoutBlockFlow {P} at (20,0) size 48x135.34 - LayoutText {#text} at (1,38) size 23x98 - text run at (1,38) width 97 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (1,38) size 23x1 - LayoutText {#text} at (25,28) size 23x108 - text run at (25,28) width 107 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,182.34) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png deleted file mode 100644 index f6b3419d..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt deleted file mode 100644 index 868dee8..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x198 - LayoutBlockFlow {HTML} at (0,0) size 800x198.34 - LayoutBlockFlow {BODY} at (8,16) size 784x169.34 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x18 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 108x135.34 - LayoutBlockFlow {P} at (20,0) size 24x135.34 - LayoutText {#text} at (1,38) size 23x98 - text run at (1,38) width 97 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (64,0) size 24x135.34 - LayoutText {#text} at (1,28) size 23x108 - text run at (1,28) width 107 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,182.34) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png deleted file mode 100644 index 56ebb508..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt deleted file mode 100644 index a45c0eb..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x198 - LayoutBlockFlow {HTML} at (0,0) size 800x198.34 - LayoutBlockFlow {BODY} at (8,16) size 784x169.34 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x18 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 88x135.34 - LayoutBlockFlow {P} at (20,0) size 48x135.34 - LayoutText {#text} at (1,38) size 23x98 - text run at (1,38) width 97 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (1,38) size 23x1 - LayoutText {#text} at (25,28) size 23x108 - text run at (25,28) width 107 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,182.34) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 6 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png deleted file mode 100644 index 0a3ea869..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt deleted file mode 100644 index 6b385dc0..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x198 - LayoutBlockFlow {HTML} at (0,0) size 800x198.34 - LayoutBlockFlow {BODY} at (8,16) size 784x169.34 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x18 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 108x135.34 - LayoutBlockFlow {P} at (20,0) size 24x135.34 - LayoutText {#text} at (1,38) size 23x98 - text run at (1,38) width 97 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (64,0) size 24x135.34 - LayoutText {#text} at (1,28) size 23x108 - text run at (1,28) width 107 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,182.34) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 6 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/popup-menu-mouse-operations-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/popup-menu-mouse-operations-expected.txt index 88dc884a..6557d56 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/popup-menu-mouse-operations-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/popup-menu-mouse-operations-expected.txt
@@ -2,4 +2,4 @@ PASS successfullyParsed is true TEST COMPLETE - +
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index 627cb9e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index f29dbb2..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 644x19 - text run at (0,0) width 644: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 19x1 - LayoutText {#text} at (20,0) size 19x119 - text run at (20,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index 9462479..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 1a921df..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 645x19 - text run at (0,0) width 645: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 19x1 - LayoutText {#text} at (20,0) size 19x119 - text run at (20,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index 24c0d1b0..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index f29dbb2..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 644x19 - text run at (0,0) width 644: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 19x1 - LayoutText {#text} at (20,0) size 19x119 - text run at (20,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png deleted file mode 100644 index afd9d89..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt deleted file mode 100644 index 239bd5e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 644x19 - text run at (0,0) width 644: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 88x210 - LayoutBlockFlow {P} at (16,0) size 20x210 - LayoutText {#text} at (0,0) size 19x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (52,0) size 20x210 - LayoutText {#text} at (0,0) size 19x119 - text run at (0,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png deleted file mode 100644 index 5180d7ec..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt deleted file mode 100644 index db56903..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x187 - LayoutBlockFlow {HTML} at (0,0) size 800x187 - LayoutBlockFlow {BODY} at (8,16) size 784x158 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 644x19 - text run at (0,0) width 644: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x122 - LayoutBlockFlow {P} at (16,0) size 40x122 - LayoutText {#text} at (0,0) size 39x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (20,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,171) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 13 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index e570721..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 1a921df..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 645x19 - text run at (0,0) width 645: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x210 - LayoutBlockFlow {P} at (16,0) size 40x210 - LayoutText {#text} at (0,0) size 19x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 19x1 - LayoutText {#text} at (20,0) size 19x119 - text run at (20,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png deleted file mode 100644 index 9e1f1af..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt deleted file mode 100644 index 5253318..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x275 - LayoutBlockFlow {HTML} at (0,0) size 800x275 - LayoutBlockFlow {BODY} at (8,16) size 784x246 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 645x19 - text run at (0,0) width 645: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 88x210 - LayoutBlockFlow {P} at (16,0) size 20x210 - LayoutText {#text} at (0,0) size 19x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (52,0) size 20x210 - LayoutText {#text} at (0,0) size 19x119 - text run at (0,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,259) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png deleted file mode 100644 index 1908204..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt deleted file mode 100644 index de907dc..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x187 - LayoutBlockFlow {HTML} at (0,0) size 800x187 - LayoutBlockFlow {BODY} at (8,16) size 784x158 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 645x19 - text run at (0,0) width 645: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,36) size 72x122 - LayoutBlockFlow {P} at (16,0) size 40x122 - LayoutText {#text} at (0,0) size 39x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (20,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,171) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 10 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png deleted file mode 100644 index d10e03d9e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt deleted file mode 100644 index 65b77f9..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 84x135 - LayoutBlockFlow {P} at (20,0) size 44x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (0,27) size 22x0 - LayoutText {#text} at (22,15) size 22x120 - text run at (22,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png deleted file mode 100644 index 622126dd..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt deleted file mode 100644 index 207c2f0c..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 104x135 - LayoutBlockFlow {P} at (20,0) size 22x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (62,0) size 22x135 - LayoutText {#text} at (0,15) size 22x120 - text run at (0,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png deleted file mode 100644 index d10e03d9e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt deleted file mode 100644 index 65b77f9..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 84x135 - LayoutBlockFlow {P} at (20,0) size 44x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (0,27) size 22x0 - LayoutText {#text} at (22,15) size 22x120 - text run at (22,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png deleted file mode 100644 index 622126dd..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt deleted file mode 100644 index 207c2f0c..0000000 --- a/third_party/WebKit/LayoutTests/platform/win-xp/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x200 - LayoutBlockFlow {HTML} at (0,0) size 800x200 - LayoutBlockFlow {BODY} at (8,16) size 784x171 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 365x19 - text run at (0,0) width 365: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,36) size 104x135 - LayoutBlockFlow {P} at (20,0) size 22x135 - LayoutText {#text} at (0,27) size 22x108 - text run at (0,27) width 108 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (62,0) size 22x135 - LayoutText {#text} at (0,15) size 22x120 - text run at (0,15) width 120 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,184) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index 90cb386..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 1c97068..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x286 - LayoutBlockFlow {HTML} at (0,0) size 800x285.69 - LayoutBlockFlow {BODY} at (8,16) size 784x256.69 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 84x214.69 - LayoutBlockFlow {P} at (16,0) size 52x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (4,128) size 17x0 - LayoutText {#text} at (30,0) size 17x128 - text run at (30,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,269.69) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index 7d182bb..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 1d063d3..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x286 - LayoutBlockFlow {HTML} at (0,0) size 800x285.69 - LayoutBlockFlow {BODY} at (8,16) size 784x256.69 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 84x214.69 - LayoutBlockFlow {P} at (16,0) size 52x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (4,128) size 17x0 - LayoutText {#text} at (30,0) size 17x128 - text run at (30,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,269.69) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index a314886..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 1c97068..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x286 - LayoutBlockFlow {HTML} at (0,0) size 800x285.69 - LayoutBlockFlow {BODY} at (8,16) size 784x256.69 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 84x214.69 - LayoutBlockFlow {P} at (16,0) size 52x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (4,128) size 17x0 - LayoutText {#text} at (30,0) size 17x128 - text run at (30,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,269.69) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png deleted file mode 100644 index 0e38290..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt deleted file mode 100644 index b0a868b6..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x286 - LayoutBlockFlow {HTML} at (0,0) size 800x285.69 - LayoutBlockFlow {BODY} at (8,16) size 784x256.69 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 100x214.69 - LayoutBlockFlow {P} at (16,0) size 26x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (58,0) size 26x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,269.69) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png deleted file mode 100644 index a314886..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt deleted file mode 100644 index cf768272..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x201 - LayoutBlockFlow {HTML} at (0,0) size 800x201 - LayoutBlockFlow {BODY} at (8,16) size 784x172 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 84x130 - LayoutBlockFlow {P} at (16,0) size 52x130 - LayoutText {#text} at (4,0) size 43x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (30,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,185) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 13 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index cb66daf5..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index 1d063d3..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x286 - LayoutBlockFlow {HTML} at (0,0) size 800x285.69 - LayoutBlockFlow {BODY} at (8,16) size 784x256.69 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 84x214.69 - LayoutBlockFlow {P} at (16,0) size 52x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (4,128) size 17x0 - LayoutText {#text} at (30,0) size 17x128 - text run at (30,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,269.69) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png deleted file mode 100644 index 3d74536..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt deleted file mode 100644 index 2c710fc..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x286 - LayoutBlockFlow {HTML} at (0,0) size 800x285.69 - LayoutBlockFlow {BODY} at (8,16) size 784x256.69 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 100x214.69 - LayoutBlockFlow {P} at (16,0) size 26x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (58,0) size 26x214.69 - LayoutText {#text} at (4,0) size 17x128 - text run at (4,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,269.69) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png deleted file mode 100644 index cb66daf5..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt deleted file mode 100644 index 291e2532..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x201 - LayoutBlockFlow {HTML} at (0,0) size 800x201 - LayoutBlockFlow {BODY} at (8,16) size 784x172 - LayoutBlockFlow {P} at (0,0) size 784x26 - LayoutText {#text} at (0,4) size 702x17 - text run at (0,4) width 702: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,42) size 84x130 - LayoutBlockFlow {P} at (16,0) size 52x130 - LayoutText {#text} at (4,0) size 43x128 - text run at (4,0) width 128: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (30,0) width 128: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,185) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 10 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png deleted file mode 100644 index 8ebaabcd..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt deleted file mode 100644 index 18bca493..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x190 - LayoutBlockFlow {HTML} at (0,0) size 800x189.84 - LayoutBlockFlow {BODY} at (8,16) size 784x160.84 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x17 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 86x126.84 - LayoutBlockFlow {P} at (20,0) size 46x126.84 - LayoutText {#text} at (0,18) size 23x109 - text run at (0,18) width 109 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (0,18) size 23x1 - LayoutText {#text} at (23,6) size 23x121 - text run at (23,6) width 121 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,173.84) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png deleted file mode 100644 index f3337a4..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt deleted file mode 100644 index fb461af..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x190 - LayoutBlockFlow {HTML} at (0,0) size 800x189.84 - LayoutBlockFlow {BODY} at (8,16) size 784x160.84 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x17 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 106x126.84 - LayoutBlockFlow {P} at (20,0) size 23x126.84 - LayoutText {#text} at (0,18) size 23x109 - text run at (0,18) width 109 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (63,0) size 23x126.84 - LayoutText {#text} at (0,6) size 23x121 - text run at (0,6) width 121 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,173.84) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png deleted file mode 100644 index 8ebaabcd..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt deleted file mode 100644 index 18bca493..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x190 - LayoutBlockFlow {HTML} at (0,0) size 800x189.84 - LayoutBlockFlow {BODY} at (8,16) size 784x160.84 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x17 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 86x126.84 - LayoutBlockFlow {P} at (20,0) size 46x126.84 - LayoutText {#text} at (0,18) size 23x109 - text run at (0,18) width 109 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBR {BR} at (0,18) size 23x1 - LayoutText {#text} at (23,6) size 23x121 - text run at (23,6) width 121 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,173.84) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png deleted file mode 100644 index f3337a4..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt deleted file mode 100644 index fb461af..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/vertical-rl-rtl-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x190 - LayoutBlockFlow {HTML} at (0,0) size 800x189.84 - LayoutBlockFlow {BODY} at (8,16) size 784x160.84 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 399x17 - text run at (0,0) width 399: "This tests horizontal caret movement in vertical writing mode." - LayoutBlockFlow {DIV} at (0,34) size 106x126.84 - LayoutBlockFlow {P} at (20,0) size 23x126.84 - LayoutText {#text} at (0,18) size 23x109 - text run at (0,18) width 109 RTL: "\x{5D0}\x{5E0}\x{5D9} \x{5D7}\x{5EA}\x{5D5}\x{5DC}." - LayoutBlockFlow {P} at (63,0) size 23x126.84 - LayoutText {#text} at (0,6) size 23x121 - text run at (0,6) width 121 RTL: "\x{5D0}\x{5D9}\x{5DF} \x{5DC}\x{5D9} \x{5E9}\x{5DD}." - LayoutBlockFlow {PRE} at (0,173.84) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 2 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/popup-menu-mouse-operations-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/popup-menu-mouse-operations-expected.txt index 55aec17..ef1d6716 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/popup-menu-mouse-operations-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/popup-menu-mouse-operations-expected.txt
@@ -23,7 +23,8 @@ PASS window.internals.pagePopupWindow is null PASS menu.value is "bar" PASS internals.selectMenuListText(menu) is "bar" +PASS picker._selectElement.selectedOptions[0].label is "option20" PASS successfullyParsed is true TEST COMPLETE - +
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index ca7be1d..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 612b040c..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x279 - LayoutBlockFlow {HTML} at (0,0) size 800x278.69 - LayoutBlockFlow {BODY} at (8,16) size 784x249.69 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 691x17 - text run at (0,1) width 691: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 68x214.69 - LayoutBlockFlow {P} at (16,0) size 36x214.69 - LayoutText {#text} at (0,0) size 17x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 17x1 - LayoutText {#text} at (18,0) size 17x119 - text run at (18,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,262.69) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index e5678ec..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index fd630e5a..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-lr-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x279 - LayoutBlockFlow {HTML} at (0,0) size 800x278.69 - LayoutBlockFlow {BODY} at (8,16) size 784x249.69 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 692x17 - text run at (0,1) width 692: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 68x214.69 - LayoutBlockFlow {P} at (16,0) size 36x214.69 - LayoutText {#text} at (0,0) size 17x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 17x1 - LayoutText {#text} at (18,0) size 17x119 - text run at (18,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,262.69) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png deleted file mode 100644 index f1f535c..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt deleted file mode 100644 index 612b040c..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x279 - LayoutBlockFlow {HTML} at (0,0) size 800x278.69 - LayoutBlockFlow {BODY} at (8,16) size 784x249.69 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 691x17 - text run at (0,1) width 691: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 68x214.69 - LayoutBlockFlow {P} at (16,0) size 36x214.69 - LayoutText {#text} at (0,0) size 17x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 17x1 - LayoutText {#text} at (18,0) size 17x119 - text run at (18,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,262.69) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png deleted file mode 100644 index 94d1fea5..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt deleted file mode 100644 index 668e5e0..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x279 - LayoutBlockFlow {HTML} at (0,0) size 800x278.69 - LayoutBlockFlow {BODY} at (8,16) size 784x249.69 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 691x17 - text run at (0,1) width 691: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 84x214.69 - LayoutBlockFlow {P} at (16,0) size 18x214.69 - LayoutText {#text} at (0,0) size 17x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (50,0) size 18x214.69 - LayoutText {#text} at (0,0) size 17x119 - text run at (0,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,262.69) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 5 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png deleted file mode 100644 index 200203d..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt deleted file mode 100644 index 0451d0b..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-backward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x186 - LayoutBlockFlow {HTML} at (0,0) size 800x186 - LayoutBlockFlow {BODY} at (8,16) size 784x157 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 691x17 - text run at (0,1) width 691: "This tests horizontal caret movement in vertical writing mode. \"\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 68x122 - LayoutBlockFlow {P} at (16,0) size 36x122 - LayoutText {#text} at (0,0) size 35x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (18,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,170) size 784x0 -selection start: position 5 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 13 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png deleted file mode 100644 index 6334b08..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt deleted file mode 100644 index fd630e5a..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-br-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x279 - LayoutBlockFlow {HTML} at (0,0) size 800x278.69 - LayoutBlockFlow {BODY} at (8,16) size 784x249.69 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 692x17 - text run at (0,1) width 692: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 68x214.69 - LayoutBlockFlow {P} at (16,0) size 36x214.69 - LayoutText {#text} at (0,0) size 17x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBR {BR} at (0,120) size 17x1 - LayoutText {#text} at (18,0) size 17x119 - text run at (18,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,262.69) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 2 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png deleted file mode 100644 index 3b5a708b..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt deleted file mode 100644 index 6acfaa2..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-p-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x279 - LayoutBlockFlow {HTML} at (0,0) size 800x278.69 - LayoutBlockFlow {BODY} at (8,16) size 784x249.69 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 692x17 - text run at (0,1) width 692: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 84x214.69 - LayoutBlockFlow {P} at (16,0) size 18x214.69 - LayoutText {#text} at (0,0) size 17x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - LayoutBlockFlow {P} at (50,0) size 18x214.69 - LayoutText {#text} at (0,0) size 17x119 - text run at (0,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,262.69) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 2 of child 0 {#text} of child 3 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png deleted file mode 100644 index 45de1f6..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt deleted file mode 100644 index 993cc458..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/vertical-rl-ltr-extend-line-forward-wrap-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x186 - LayoutBlockFlow {HTML} at (0,0) size 800x186 - LayoutBlockFlow {BODY} at (8,16) size 784x157 - LayoutBlockFlow {P} at (0,0) size 784x19 - LayoutText {#text} at (0,1) size 692x17 - text run at (0,1) width 692: "This tests horizontal caret movement in vertical writing mode. \"\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}\" and \"\x{540D}\x{524D}\" must be selected." - LayoutBlockFlow {DIV} at (0,35) size 68x122 - LayoutBlockFlow {P} at (16,0) size 36x122 - LayoutText {#text} at (0,0) size 35x121 - text run at (0,0) width 121: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067}\x{3042}\x{308B}\x{3002}" - text run at (18,0) width 119: "\x{540D}\x{524D}\x{306F}\x{307E}\x{3060}\x{7121}\x{3044}\x{3002}" - LayoutBlockFlow {PRE} at (0,170) size 784x0 -selection start: position 2 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body -selection end: position 10 of child 0 {#text} of child 1 {P} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt index 689838d..b8b5f094 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -3122,7 +3122,9 @@ interface OfflineAudioContext : AudioContext getter oncomplete method constructor + method resume method startRendering + method suspend setter oncomplete interface Option method constructor @@ -5635,7 +5637,9 @@ interface webkitOfflineAudioContext : AudioContext getter oncomplete method constructor + method resume method startRendering + method suspend setter oncomplete interface webkitRTCPeerConnection : EventTarget getter iceConnectionState
diff --git a/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume-expected.txt b/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume-expected.txt index 0eede07..cc4a1e7f2 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume-expected.txt +++ b/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume-expected.txt
@@ -7,15 +7,15 @@ PASS offlineContext.state is "suspended" PASS p1 = offlineContext.suspend() did not throw exception. PASS p1 is an instance of Promise -PASS offlineContext.suspend() was correctly rejected: InvalidAccessError: cannot suspend an OfflineAudioContext +PASS offlineContext.suspend() was correctly rejected: TypeError: Failed to execute 'suspend' on 'OfflineAudioContext': 1 argument required, but only 0 present. PASS p2 = offlineContext.resume() did not throw exception. PASS p2 is an instance of Promise PASS offlineContext.state is "suspended" -PASS offlineContext.resume() was correctly rejected: InvalidAccessError: cannot resume an OfflineAudioContext +PASS offlineContext.resume() was correctly rejected: InvalidStateError: cannot resume an offline context that has not started PASS p3 = offlineContext.startRendering() did not throw exception. PASS offlineContext.state is "closed" -PASS offlineContext.suspend() on a closed context rejected: InvalidAccessError: cannot suspend an OfflineAudioContext -PASS offlineContext.resume() on a closed context rejected: InvalidAccessError: cannot resume an OfflineAudioContext +PASS offlineContext.suspend() on a closed context rejected: TypeError: Failed to execute 'suspend' on 'OfflineAudioContext': 1 argument required, but only 0 present. +PASS offlineContext.resume() on a closed context rejected: InvalidStateError: cannot resume a closed offline context PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume.html b/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume.html index 8c16380..0e71230f 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume.html +++ b/third_party/WebKit/LayoutTests/webaudio/audiocontext-suspend-resume.html
@@ -57,12 +57,12 @@ p1.then( handlePromise(testFailed, "offlineContext.suspend() should have been rejected for an offline context"), function (e) { - if (e.name === "InvalidAccessError") { + if (e.name === "TypeError") { testPassed( "offlineContext.suspend() was correctly rejected: " + e); } else { testFailed( - "offlineContext.suspend() was correctly rejected but expected InvalidAccessError, not: " + e); + "offlineContext.suspend() was correctly rejected but expected TypeError, not: " + e); } } ).then(done); @@ -83,7 +83,7 @@ p2.then( handlePromise(testFailed, "offlineContext.resume() should have been rejected for an offline context"), function (e) { - if (e.name === "InvalidAccessError") { + if (e.name === "InvalidStateError") { testPassed( "offlineContext.resume() was correctly rejected: " + e); } else { @@ -110,10 +110,10 @@ offlineContext.suspend().then( handlePromise(testFailed, "offlineContext.suspend() on a closed context not rejected"), function (e) { - if (e.name === "InvalidAccessError") { + if (e.name === "TypeError") { testPassed("offlineContext.suspend() on a closed context rejected: " + e); } else { - testFailed("offlineContext.suspend() on a closed context rejected but expected InvalidAccessError, not: " + e); + testFailed("offlineContext.suspend() on a closed context rejected but expected TypeError, not: " + e); } } ).then(function () { @@ -121,10 +121,10 @@ offlineContext.resume().then( handlePromise(testFailed, "offlineContext.resume() on a closed context not rejected"), function (e) { - if (e.name === "InvalidAccessError") { + if (e.name === "InvalidStateError") { testPassed("offlineContext.resume() on a closed context rejected: " + e); } else { - testFailed("offlineContext.resume() on a closed context rejected but expected InvalidAccessError, not: " + e); + testFailed("offlineContext.resume() on a closed context rejected but expected InvalidStateError, not: " + e); } } ).then(done);
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-basic-expected.txt b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-basic-expected.txt new file mode 100644 index 0000000..446e589 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-basic-expected.txt
@@ -0,0 +1,19 @@ +Basic test for OfflineAudioContext.suspend() and OfflineAudioContext.resume(). + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS context.suspend() rejected correctly (with TypeError: Failed to execute 'suspend' on 'OfflineAudioContext': 1 argument required, but only 0 present.). +PASS context.suspend(-1.0) rejected correctly (with InvalidStateError: negative suspend time (-1) is not allowed). +PASS context.suspend(2.0) rejected correctly (with InvalidStateError: cannot schedule a suspend at frame 88192 (2 seconds) because it is greater than or equal to the total render duration of 44100 frames). +PASS Scheduling a suspend in the past rejected correctly (with InvalidStateError: cannot schedule a suspend at frame 17536 (0.399229 seconds) because it is earlier than the current frame of 22016 (0.499229 seconds)). +PASS Scheduling a suspend in the future resolved correctly. +PASS Scheduling a suspend at frame 128 was successful. +PASS Scheduling another suspend at the same rendering quantum rejected correctly (with InvalidStateError: cannot schedule more than one suspend at frame 128 (0.00435374 seconds)). +PASS Scheduling a suspend at 4.5 seconds. +PASS Resuming a running context resolved correctly. +PASS Resuming a context without starting it rejected correctly (with InvalidStateError: cannot resume an offline context that has not started). +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-basic.html b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-basic.html new file mode 100644 index 0000000..510ce51 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-basic.html
@@ -0,0 +1,136 @@ +<!doctype html> +<html> + <head> + <script src="../resources/js-test.js"></script> + <script src="resources/compatibility.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + + <body> + <script> + description('Basic test for OfflineAudioContext.suspend() and OfflineAudioContext.resume().'); + window.jsTestIsAsync = true; + + var sampleRate = 44100; + var renderDuration = 1; + var renderQuantum = 128; + + var audit = Audit.createTaskRunner(); + + // Task: Calling suspend with no argument, negative time or the time + // beyond the maximum render duration reject the promise. + audit.defineTask('suspend-invalid-argument', function (done) { + var context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + Should('context.suspend()', context.suspend()).beRejected(); + Should('context.suspend(-1.0)', context.suspend(-1.0)).beRejected(); + Should('context.suspend(2.0)', context.suspend(2.0)).beRejected(); + + context.startRendering().then(done); + }); + + // Task: Scheduling a suspend in the past should be rejected. + audit.defineTask('suspend-in-the-past', function (done) { + var context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + context.suspend(0.5).then(function () { + + Should('Scheduling a suspend in the past', + context.suspend(context.currentTime - 0.1)).beRejected(); + + Should('Scheduling a suspend in the future', + context.suspend(context.currentTime + 0.1).then(function () { + context.resume(); + })).beResolved(); + + context.resume(); + }); + + context.startRendering().then(done); + }); + + // Task: Calling multiple suspends at the same rendering quantum should + // reject the promise. + audit.defineTask('identical-suspend-time', function (done) { + var context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + // |suspendTime1| and |suspendTime2| are identical when quantized to + // the render quantum size. + var suspendTime1 = renderQuantum / sampleRate; + var suspendTime2 = 1.5 * renderQuantum / sampleRate; + + context.suspend(suspendTime1).then(function () { + context.resume(); + }); + + // Printing out the pass message to be more informative here. + testPassed('Scheduling a suspend at frame ' + suspendTime1 * sampleRate + ' was successful.'); + + Should('Scheduling another suspend at the same rendering quantum', + context.suspend(suspendTime2)).beRejected(); + + context.startRendering().then(done); + }); + + // Task: Resuming a running context should be resolved. + audit.defineTask('resume-before-suspend', function (done) { + + // Make the render length 5 times longer to minimize the flakiness. + var longRenderDuration = renderDuration * 5; + var context = new OfflineAudioContext(1, sampleRate * longRenderDuration, sampleRate); + + // Create dummy audio graph to slow the rendering. + var osc = context.createOscillator(); + var lpf = context.createBiquadFilter(); + osc.type = 'sawtooth'; + osc.frequency.setValueAtTime(0.1, 0.0); + osc.frequency.linearRampToValueAtTime(1000, longRenderDuration * 0.5); + osc.frequency.linearRampToValueAtTime(0.1, longRenderDuration); + lpf.frequency.setValueAtTime(0.1, 0.0); + lpf.frequency.linearRampToValueAtTime(1000, longRenderDuration * 0.5); + lpf.frequency.linearRampToValueAtTime(0.1, longRenderDuration); + osc.connect(lpf); + lpf.connect(context.destination); + osc.start(); + + // A suspend is scheduled at the 90% of the render duration. + context.suspend(longRenderDuration * 0.9).then(done); + + testPassed('Scheduling a suspend at ' + longRenderDuration * 0.9 + ' seconds.'); + + // We have to start rendering to get the time running. + context.startRendering(); + + // Then call resume() immediately after the rendering starts. Resuming + // a context that is already running should be resolved. + Should('Resuming a running context', context.resume()) + .beResolved(); + }); + + // Task: Calling resume on a context that is not started should reject the promise. + audit.defineTask('resume-without-suspend', function (done) { + var context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + Should('Resuming a context without starting it', context.resume()) + .beRejected().then(done); + }); + + audit.defineTask('finish', function (done) { + finishJSTest(); + done(); + }); + + audit.runTasks( + 'suspend-invalid-argument', + 'suspend-in-the-past', + 'identical-suspend-time', + 'resume-before-suspend', + 'resume-without-suspend', + 'finish' + ); + + successfullyParsed = true; + </script> + + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-eventhandler-expected.txt b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-eventhandler-expected.txt new file mode 100644 index 0000000..e4b6237 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-eventhandler-expected.txt
@@ -0,0 +1,27 @@ +Test event handler callback from OfflineAudioContext.resume() and OfflineAudioContext.suspend(). + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS A new suspend has been scheduled at 0 second(s). +PASS onstatechange event handler: context is suspended at 0 second(s). +PASS A new suspend has been scheduled at 0.25 second(s). +PASS onstatechange event handler: context is suspended at 0.25 second(s). +PASS A new suspend has been scheduled at 0.5 second(s). +PASS onstatechange event handler: context is suspended at 0.5 second(s). +PASS A new suspend has been scheduled at 0.75 second(s). +PASS onstatechange event handler: context is suspended at 0.75 second(s). +PASS A new suspend has been scheduled at 1 second(s). +PASS onstatechange event handler: context is suspended at 1 second(s). +PASS A new suspend has been scheduled at 1.25 second(s). +PASS onstatechange event handler: context is suspended at 1.25 second(s). +PASS A new suspend has been scheduled at 1.5 second(s). +PASS onstatechange event handler: context is suspended at 1.5 second(s). +PASS A new suspend has been scheduled at 1.75 second(s). +PASS onstatechange event handler: context is suspended at 1.75 second(s). +PASS Scheduling at 2 seconds rejected correctly (with InvalidStateError: cannot schedule a suspend at frame 25600 (2 seconds) because it is greater than or equal to the total render duration of 25600 frames). +PASS oncomplete event handler: context.state is equal to closed. +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-eventhandler.html b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-eventhandler.html new file mode 100644 index 0000000..8bb7dc4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-eventhandler.html
@@ -0,0 +1,77 @@ +<!doctype html> +<html> + <head> + <script src="../resources/js-test.js"></script> + <script src="resources/compatibility.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + + <body> + <script> + description('Test event handler callback from OfflineAudioContext.resume() and OfflineAudioContext.suspend().'); + window.jsTestIsAsync = true; + + var context; + var renderQuantum = 128; + + // The sample rate is multiple of the rendering quantum, so suspension + // times in the test will fall on the render quantum boundary. Although + // this is not necessary, it is easier to understand the test. + var sampleRate = renderQuantum * 100; + + var renderDuration = 2; + var scheduledSuspendTime = 0; + + // With the sample rate setting above, this ensures suspension time fall + // in to the render quantum boundary. + var suspendInterval = 0.25; + + function runTest() { + context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + context.onstatechange = function () { + if (context.state === 'suspended' && context.currentTime === scheduledSuspendTime) { + + testPassed('onstatechange event handler: context is suspended at ' + + scheduledSuspendTime + ' second(s).'); + + scheduledSuspendTime = context.currentTime + suspendInterval; + + // Scheduling a suspend before the render duration should pass. + if (scheduledSuspendTime < renderDuration) { + context.suspend(scheduledSuspendTime); + testPassed('A new suspend has been scheduled at ' + + scheduledSuspendTime + ' second(s).'); + } + + // Scheduling a suspend exactly at the render duration should be + // rejected. + if (scheduledSuspendTime === renderDuration) { + Should('Scheduling at ' + renderDuration + ' seconds', + context.suspend(scheduledSuspendTime)).beRejected(); + } + + context.resume(); + } + }; + + // This test is for verifying all the event handlers on OAC and that is + // why 'oncomplete' is used here. + context.oncomplete = function () { + Should('oncomplete event handler: context.state', context.state).beEqualTo('closed'); + finishJSTest(); + }; + + // Schedule the first suspension. + context.suspend(scheduledSuspendTime); + testPassed('A new suspend has been scheduled at ' + scheduledSuspendTime + ' second(s).'); + + context.startRendering(); + } + + runTest(); + successfullyParsed = true; + </script> + + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-graph-manipulation-expected.txt b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-graph-manipulation-expected.txt new file mode 100644 index 0000000..e5a3e36 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-graph-manipulation-expected.txt
@@ -0,0 +1,16 @@ +Test synchronous graph manipulation with OfflineAudioContext.suspend() and OfflineAudioContext.resume(). + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS Context is suspended at 12800 frame as expected. +PASS A constant buffer is connected to destination and started at 12800 frame. +PASS Context is suspended at 25600 frame as expected. +PASS A constant buffer is disconnected at 25600 frame. +PASS Buffer frame [0, 12800) contains only the constant 0. +PASS Buffer frame [12800, 25600) contains only the constant 1. +PASS Buffer frame [25600, 38400) contains only the constant 0. +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-graph-manipulation.html b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-graph-manipulation.html new file mode 100644 index 0000000..a996ac2c --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-graph-manipulation.html
@@ -0,0 +1,93 @@ +<!doctype html> +<html> + <head> + <script src="../resources/js-test.js"></script> + <script src="resources/compatibility.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + + <body> + <script> + description('Test synchronous graph manipulation with OfflineAudioContext.suspend() and OfflineAudioContext.resume().'); + window.jsTestIsAsync = true; + + var context; + var renderQuantum = 128; + var renderDuration = 3; + + // The sample rate is multiple of the rendering quantum, so suspension + // times fall in to the render quantum boundary. + var sampleRate = renderQuantum * 100; + + context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + // Create a constant buffer of 1.0. + var constantBuffer = createConstantBuffer(context, 1, 1.0); + var constantSource = context.createBufferSource(); + constantSource.buffer = constantBuffer; + constantSource.loop = true; + + // The audio output from the beginning (0.0 second) to the first suspend + // time should be 0.0 because there is no connection to the destination. + + // Suspend at 1 second and activate the source node. The audio output + // should be 1.0 from |suspendTime1| to the next suspension. + var suspendTime1 = 1; + context.suspend(suspendTime1).then(function () { + if (context.currentTime === suspendTime1) + testPassed('Context is suspended at ' + suspendTime1 * sampleRate + ' frame as expected.'); + + constantSource.connect(context.destination); + constantSource.start(); + testPassed('A constant buffer is connected to destination and started at ' + + suspendTime1 * sampleRate + ' frame.'); + + context.resume(); + }); + + // Suspend at 2 seconds and disconnect the node. The audio output should + // be 0.0 from |suspendTime2| to the end. + var suspendTime2 = 2; + context.suspend(suspendTime2).then(function () { + if (context.currentTime === suspendTime2) + testPassed('Context is suspended at ' + suspendTime2 * sampleRate + ' frame as expected.'); + + constantSource.disconnect(); + testPassed('A constant buffer is disconnected at ' + suspendTime2 * sampleRate + ' frame.'); + + context.resume(); + }); + + context.startRendering().then(function (buffer) { + verifyResult(buffer); + finishJSTest(); + }); + + function verifyResult(buffer) { + var data = buffer.getChannelData(0); + + var suspendIndex1 = suspendTime1 * sampleRate; + var suspendIndex2 = suspendTime2 * sampleRate; + var endIndex = renderDuration * sampleRate; + + // Split the rendered buffer into 3 segments: + // [0, suspendIndex1), [suspendIndex1, suspendIndex2), [suspendIndex2, + // endIndex). + var subarray0 = data.subarray(0, suspendIndex1); + var subarray1 = data.subarray(suspendIndex1, suspendIndex2); + var subarray2 = data.subarray(suspendIndex2, endIndex); + + // Each segment should contain a constant value of 0, 1 and 0 + // respectively. + Should('Buffer frame [0, ' + suspendIndex1 + ')', subarray0).beConstantValueOf(0); + Should('Buffer frame [' + suspendIndex1 + ', ' + suspendIndex2 + ')', subarray1) + .beConstantValueOf(1); + Should('Buffer frame [' + suspendIndex2 + ', ' + endIndex + ')', subarray2) + .beConstantValueOf(0); + } + + successfullyParsed = true; + </script> + + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-promise-expected.txt b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-promise-expected.txt new file mode 100644 index 0000000..a4ce359f --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-promise-expected.txt
@@ -0,0 +1,27 @@ +Test promise resolution of OfflineAudioContext.resume() and OfflineAudioContext.suspend(). + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS A new suspend has been scheduled at 0 second(s). +PASS suspend promise resolved: context is suspended at 0 second(s). +PASS A new suspend has been scheduled at 0.25 second(s). +PASS suspend promise resolved: context is suspended at 0.25 second(s). +PASS A new suspend has been scheduled at 0.5 second(s). +PASS suspend promise resolved: context is suspended at 0.5 second(s). +PASS A new suspend has been scheduled at 0.75 second(s). +PASS suspend promise resolved: context is suspended at 0.75 second(s). +PASS A new suspend has been scheduled at 1 second(s). +PASS suspend promise resolved: context is suspended at 1 second(s). +PASS A new suspend has been scheduled at 1.25 second(s). +PASS suspend promise resolved: context is suspended at 1.25 second(s). +PASS A new suspend has been scheduled at 1.5 second(s). +PASS suspend promise resolved: context is suspended at 1.5 second(s). +PASS A new suspend has been scheduled at 1.75 second(s). +PASS suspend promise resolved: context is suspended at 1.75 second(s). +PASS Scheduling at 2 seconds rejected correctly (with InvalidStateError: cannot schedule a suspend at frame 25600 (2 seconds) because it is greater than or equal to the total render duration of 25600 frames). +PASS Promise context.state is equal to closed. +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-promise.html b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-promise.html new file mode 100644 index 0000000..f898da9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-promise.html
@@ -0,0 +1,68 @@ +<!doctype html> +<html> + <head> + <script src="../resources/js-test.js"></script> + <script src="resources/compatibility.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + + <body> + <script> + description('Test promise resolution of OfflineAudioContext.resume() and OfflineAudioContext.suspend().'); + window.jsTestIsAsync = true; + + var context; + + // The sample rate is multiple of the rendering quantum, so suspension + // times fall in to the render quantum boundary. + var renderQuantum = 128; + + var sampleRate = renderQuantum * 100; + var renderDuration = 2; + var scheduledSuspendTime = 0; + + // With the sample rate setting above, this ensures suspension time fall + // in to the render quantum boundary. + var suspendInterval = 0.25; + + context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + function onSuspended() { + if (context.state === 'suspended' && context.currentTime === scheduledSuspendTime) { + + testPassed('suspend promise resolved: context is suspended at ' + + scheduledSuspendTime + ' second(s).'); + + scheduledSuspendTime = context.currentTime + suspendInterval; + + // Scheduling a suspend before the render duration should pass. + if (scheduledSuspendTime < renderDuration) { + context.suspend(scheduledSuspendTime).then(onSuspended); + testPassed('A new suspend has been scheduled at ' + + scheduledSuspendTime + ' second(s).'); + } + + // Scheduling a suspend exactly at the render duration should be + // rejected. + if (scheduledSuspendTime === renderDuration) { + Should('Scheduling at ' + renderDuration + ' seconds', + context.suspend(scheduledSuspendTime)).beRejected(); + } + + context.resume(); + } + } + + // Schedule the first suspension. + context.suspend(scheduledSuspendTime).then(onSuspended); + testPassed('A new suspend has been scheduled at ' + scheduledSuspendTime + ' second(s).'); + + context.startRendering().then(function () { + Should('Promise context.state', context.state).beEqualTo('closed'); + }).then(finishJSTest); + + successfullyParsed = true; + </script> + + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-sequence-expected.txt b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-sequence-expected.txt new file mode 100644 index 0000000..3fd3d66 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-sequence-expected.txt
@@ -0,0 +1,23 @@ +Test OfflineAudioContext.resume() and OfflineAudioContext.suspend() with the timed sequence. + +On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + + +PASS Scheduling suspend #0 at 0.25 second(s). +PASS Scheduling suspend #1 at 0.75 second(s). +PASS Scheduling suspend #2 at 1 second(s). +PASS Scheduling suspend #3 at 0.5 second(s). +PASS Scheduling suspend #4 at 1.25 second(s). +PASS Scheduling suspend #5 at 0 second(s). +PASS Scheduling suspend #6 at 1.75 second(s). +PASS The resolution order of suspend #5 is 0 at 0.00 second(s). +PASS The resolution order of suspend #0 is 1 at 0.25 second(s). +PASS The resolution order of suspend #3 is 2 at 0.50 second(s). +PASS The resolution order of suspend #1 is 3 at 0.75 second(s). +PASS The resolution order of suspend #2 is 4 at 1.00 second(s). +PASS The resolution order of suspend #4 is 5 at 1.25 second(s). +PASS The resolution order of suspend #6 is 6 at 1.75 second(s). +PASS successfullyParsed is true + +TEST COMPLETE +
diff --git a/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-sequence.html b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-sequence.html new file mode 100644 index 0000000..334fa40 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/offlineaudiocontext-suspend-resume-sequence.html
@@ -0,0 +1,77 @@ +<!doctype html> +<html> + <head> + <script src="../resources/js-test.js"></script> + <script src="resources/compatibility.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + + <body> + <script> + description('Test OfflineAudioContext.resume() and OfflineAudioContext.suspend() with the timed sequence.'); + window.jsTestIsAsync = true; + + var context; + + // The sample rate is multiple of the rendering quantum, so suspension + // times fall in to the render quantum boundary. + var renderQuantum = 128; + + var sampleRate = renderQuantum * 100; + var renderDuration = 2; + + // These numbers are in an arbitrary order, but not randomly generated in + // runtime to avoid moving pieces. However, it is safe to arrange them + // in a random order in runtime. + // + // Also these numbers are multiple of 0.25, so they are supposed to fall + // in the render quantum boundary for easier and more intuitive + // verification. + var suspendTimes = [0.25, 0.75, 1.0, 0.5, 1.25, 0.0, 1.75]; + + // Sorted ascending suspend time is our expected result. + var expectedSuspendTimes = suspendTimes.slice(0).sort(function (a, b) { + return a - b; + }); + + var actualSuspendTimes = []; + + context = new OfflineAudioContext(1, sampleRate * renderDuration, sampleRate); + + for (var i = 0; i < suspendTimes.length; i++) { + + // Schedule suspends in a random time order, but the actual suspend + // must happen in ascending time order. + scheduleSuspend(i, suspendTimes[i]); + + } + + function scheduleSuspend(index, suspendTime) { + testPassed('Scheduling suspend #' + index + ' at ' + suspendTime + ' second(s).'); + context.suspend(suspendTime).then(function () { + actualSuspendTimes.push(suspendTime); + context.resume(); + }) + } + + function verifyResult() { + + for (var i = 0; i < actualSuspendTimes.length; i++) { + var scheduledOrder = suspendTimes.indexOf(actualSuspendTimes[i]); + var expectedOrder = expectedSuspendTimes.indexOf(actualSuspendTimes[i]); + + if (i === expectedOrder) { + testPassed('The resolution order of suspend #' + scheduledOrder + + ' is ' + i + ' at ' + suspendTimes[scheduledOrder].toFixed(2) + + ' second(s).'); + } + } + } + + context.startRendering().then(verifyResult).then(finishJSTest); + + successfullyParsed = true; + </script> + + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js b/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js index 2592562..a838881c 100644 --- a/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js +++ b/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js
@@ -785,6 +785,36 @@ return this._success; }; + // Check if the target promise is resolved correctly. + // + // Example: + // Should('My promise', promise).beResolved().then(nextStuff); + // Result: + // "PASS My promise resolved correctly." + // "FAIL My promise rejected incorrectly (with _ERROR_)." + ShouldModel.prototype.beResolved = function () { + return this.target.then(function () { + this._testPassed('resolved correctly'); + }.bind(this), function (err) { + this._testFailed('rejected incorrectly (with ' + err + ')'); + }.bind(this)); + }; + + // Check if the target promise is rejected correctly. + // + // Example: + // Should('My promise', promise).beRejected().then(nextStuff); + // Result: + // "PASS My promise rejected correctly (with _ERROR_)." + // "FAIL My promise resolved incorrectly." + ShouldModel.prototype.beRejected = function () { + return this.target.then(function () { + this._testFailed('resolved incorrectly'); + }.bind(this), function (err) { + this._testPassed('rejected correctly (with ' + err + ')'); + }.bind(this)); + }; + // Should() method. // // |desc| is the description of the task or check and |target| is a value
diff --git a/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt b/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt index 0f9148f..7232672 100644 --- a/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt
@@ -105,6 +105,7 @@ floodColor floodOpacity font +fontDisplay fontFamily fontFeatureSettings fontKerning
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 33715ca..dd8a38b 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3606,7 +3606,9 @@ interface OfflineAudioContext : AudioContext getter oncomplete method constructor + method resume method startRendering + method suspend setter oncomplete interface Option method constructor @@ -6382,7 +6384,9 @@ interface webkitOfflineAudioContext : AudioContext getter oncomplete method constructor + method resume method startRendering + method suspend setter oncomplete interface webkitRTCPeerConnection : EventTarget static method generateCertificate
diff --git a/third_party/WebKit/ManualTests/goBack-blank-tab-page.html b/third_party/WebKit/ManualTests/goBack-blank-tab-page.html index 7a6157e6..df01b3a 100644 --- a/third_party/WebKit/ManualTests/goBack-blank-tab-page.html +++ b/third_party/WebKit/ManualTests/goBack-blank-tab-page.html
@@ -12,7 +12,7 @@ <br> This test checks if you can go back to a _blank-target previously tab-opened page. <br> -If the webkit doesn't meet an assertion error : this test is Successfull. +If the webkit doesn't meet an assertion error : this test is Successful. <br> When you click on the above link, one page (with _blank target) is loaded and this page will open a link and go back. </body>
diff --git a/third_party/WebKit/ManualTests/resources/before-go-back.html b/third_party/WebKit/ManualTests/resources/before-go-back.html index 10d8dbe9..8817648 100644 --- a/third_party/WebKit/ManualTests/resources/before-go-back.html +++ b/third_party/WebKit/ManualTests/resources/before-go-back.html
@@ -12,6 +12,6 @@ <br> When you click on the above link, one page is loaded and tries to go back. <br> -If the webkit doesn't meet an assertion failure : this test is successfull. +If the webkit doesn't meet an assertion failure : this test is successful. </body> </html>
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp b/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp index a8c1c70..524680e 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp
@@ -48,19 +48,17 @@ , m_isAttribute(isAttribute) , m_world(world) , m_isolate(isolate) + , m_workerGlobalScope(nullptr) { if (isMainThread()) InstanceCounters::incrementCounter(InstanceCounters::JSEventListenerCounter); + else + m_workerGlobalScope = toWorkerGlobalScope(currentExecutionContext(isolate)); } V8AbstractEventListener::~V8AbstractEventListener() { - if (!m_listener.isEmpty()) { - v8::HandleScope scope(isolate()); - // We can't use a ScriptState::Scope here as the per-context data might already be gone at this point. - v8::Context::Scope contextScope(m_scriptStateForListener->context()); - V8EventListenerList::clearWrapper(m_listener.newLocal(isolate()), m_isAttribute, m_scriptStateForListener.get()); - } + ASSERT(m_listener.isEmpty()); if (isMainThread()) InstanceCounters::decrementCounter(InstanceCounters::JSEventListenerCounter); } @@ -102,11 +100,21 @@ invokeEventHandler(scriptState, event, v8::Local<v8::Value>::New(isolate(), jsEvent)); } -void V8AbstractEventListener::setListenerObject(v8::Local<v8::Object> listener, ScriptState* scriptState) +void V8AbstractEventListener::setListenerObject(v8::Local<v8::Object> listener) { + ASSERT(m_listener.isEmpty()); + // Balanced in secondWeakCallback xor clearListenerObject. + if (m_workerGlobalScope) { + m_workerGlobalScope->registerEventListener(this); + } else { +#if ENABLE(OILPAN) + m_keepAlive = this; +#else + ref(); +#endif + } m_listener.set(isolate(), listener); m_listener.setWeak(this, &setWeakCallback); - m_scriptStateForListener = scriptState; } void V8AbstractEventListener::invokeEventHandler(ScriptState* scriptState, Event* event, v8::Local<v8::Value> jsEvent) @@ -184,10 +192,47 @@ return ScriptState::hasCurrentScriptState(isolate()) && &world() == &DOMWrapperWorld::current(isolate()); } -void V8AbstractEventListener::setWeakCallback(const v8::WeakCallbackInfo<V8AbstractEventListener> &data) +void V8AbstractEventListener::clearListenerObject() +{ + if (!hasExistingListenerObject()) + return; + m_listener.clear(); + if (m_workerGlobalScope) { + m_workerGlobalScope->deregisterEventListener(this); + } else { +#if ENABLE(OILPAN) + m_keepAlive.clear(); +#else + deref(); +#endif + } +} + +void V8AbstractEventListener::setWeakCallback(const v8::WeakCallbackInfo<V8AbstractEventListener>& data) { data.GetParameter()->m_listener.clear(); - data.GetParameter()->m_scriptStateForListener.clear(); + data.SetSecondPassCallback(secondWeakCallback); +} + +void V8AbstractEventListener::secondWeakCallback(const v8::WeakCallbackInfo<V8AbstractEventListener>& data) +{ + if (data.GetParameter()->m_workerGlobalScope) { + data.GetParameter()->m_workerGlobalScope->deregisterEventListener(data.GetParameter()); + } else { +#if ENABLE(OILPAN) + data.GetParameter()->m_keepAlive.clear(); +#else + data.GetParameter()->deref(); +#endif + } +} + +DEFINE_TRACE(V8AbstractEventListener) +{ +#if ENABLE(OILPAN) + visitor->trace(m_workerGlobalScope); +#endif + EventListener::trace(visitor); } } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.h b/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.h index fdb454f..ea19fbaa 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.h
@@ -42,6 +42,7 @@ namespace blink { class Event; +class WorkerGlobalScope; // There are two kinds of event listeners: HTML or non-HMTL. onload, // onfocus, etc (attributes) are always HTML event handler type; Event @@ -105,31 +106,20 @@ return !m_listener.isEmpty(); } - void clearListenerObject() - { - m_listener.clear(); - } + void clearListenerObject(); bool belongsToTheCurrentWorld() const final; v8::Isolate* isolate() const { return m_isolate; } DOMWrapperWorld& world() const { return *m_world; } - // Oilpan: promptly clear listener wrapper. - EAGERLY_FINALIZE(); -#if ENABLE(OILPAN) - DECLARE_EAGER_FINALIZATION_OPERATOR_NEW(); -#endif - DEFINE_INLINE_VIRTUAL_TRACE() - { - EventListener::trace(visitor); - } + DECLARE_VIRTUAL_TRACE(); protected: V8AbstractEventListener(bool isAttribute, DOMWrapperWorld&, v8::Isolate*); virtual void prepareListenerObject(ExecutionContext*) { } - void setListenerObject(v8::Local<v8::Object>, ScriptState*); + void setListenerObject(v8::Local<v8::Object>); void invokeEventHandler(ScriptState*, Event*, v8::Local<v8::Value>); @@ -147,9 +137,8 @@ virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue); static void setWeakCallback(const v8::WeakCallbackInfo<V8AbstractEventListener>&); + static void secondWeakCallback(const v8::WeakCallbackInfo<V8AbstractEventListener>&); - // The ScriptState the m_listener below was created in. - RefPtr<ScriptState> m_scriptStateForListener; ScopedPersistent<v8::Object> m_listener; // Indicates if this is an HTML type listener. @@ -157,6 +146,13 @@ RefPtr<DOMWrapperWorld> m_world; v8::Isolate* m_isolate; + + // nullptr unless this listener belongs to a worker. + RawPtrWillBeMember<WorkerGlobalScope> m_workerGlobalScope; + +#if ENABLE(OILPAN) + SelfKeepAlive<V8AbstractEventListener> m_keepAlive; +#endif }; } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp index e0b3f97..64f57415 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp
@@ -42,8 +42,8 @@ namespace blink { -V8ErrorHandler::V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) - : V8EventListener(listener, isInline, scriptState) +V8ErrorHandler::V8ErrorHandler(bool isInline, ScriptState* scriptState) + : V8EventListener(isInline, scriptState) { }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h index 1346a11e..0466f0df 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.h
@@ -43,12 +43,14 @@ public: static PassRefPtrWillBeRawPtr<V8ErrorHandler> create(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) { - return adoptRefWillBeNoop(new V8ErrorHandler(listener, isInline, scriptState)); + RefPtrWillBeRawPtr<V8ErrorHandler> eventListener = adoptRefWillBeNoop(new V8ErrorHandler(isInline, scriptState)); + eventListener->setListenerObject(listener); + return eventListener.release(); } static void storeExceptionOnErrorEventWrapper(ScriptState*, ErrorEvent*, v8::Local<v8::Value>, v8::Local<v8::Object> creationContext); private: - V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, ScriptState*); + V8ErrorHandler(bool isInline, ScriptState*); v8::Local<v8::Value> callListenerFunction(ScriptState*, v8::Local<v8::Value>, Event*) override; bool shouldPreventDefault(v8::Local<v8::Value> returnValue) override; };
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8EventListener.cpp b/third_party/WebKit/Source/bindings/core/v8/V8EventListener.cpp index 08ed566..951197a 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8EventListener.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8EventListener.cpp
@@ -38,10 +38,9 @@ namespace blink { -V8EventListener::V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, ScriptState* scriptState) +V8EventListener::V8EventListener(bool isAttribute, ScriptState* scriptState) : V8AbstractEventListener(isAttribute, scriptState->world(), scriptState->isolate()) { - setListenerObject(listener, scriptState); } v8::Local<v8::Function> V8EventListener::getListenerFunction(ScriptState* scriptState)
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h b/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h index a9a00b4..5b6423d 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8EventListener.h
@@ -45,11 +45,13 @@ public: static PassRefPtrWillBeRawPtr<V8EventListener> create(v8::Local<v8::Object> listener, bool isAttribute, ScriptState* scriptState) { - return adoptRefWillBeNoop(new V8EventListener(listener, isAttribute, scriptState)); + RefPtrWillBeRawPtr<V8EventListener> eventListener = adoptRefWillBeNoop(new V8EventListener(isAttribute, scriptState)); + eventListener->setListenerObject(listener); + return eventListener.release(); } protected: - V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, ScriptState*); + V8EventListener(bool isAttribute, ScriptState*); v8::Local<v8::Function> getListenerFunction(ScriptState*); v8::Local<v8::Value> callListenerFunction(ScriptState*, v8::Local<v8::Value>, Event*) override; };
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp index 927ec41..056dc09 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp
@@ -112,6 +112,13 @@ return; } + // MinorGC does not collect objects because it may be expensive to + // update references during minorGC + if (classId == WrapperTypeInfo::ObjectClassId) { + v8::Persistent<v8::Object>::Cast(*value).MarkActive(); + return; + } + v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(m_isolate, v8::Persistent<v8::Object>::Cast(*value)); ASSERT(V8DOMWrapper::hasInternalFieldsSet(wrapper)); const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper);
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp b/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp index d5a989d..7ca63fd 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp
@@ -203,7 +203,7 @@ // m_code = String(); // m_eventParameterName = String(); // m_sourceURL = String(); - setListenerObject(wrappedFunction, scriptState); + setListenerObject(wrappedFunction); } void V8LazyEventListener::fireErrorEvent(v8::Local<v8::Context> v8Context, ExecutionContext* executionContext, v8::Local<v8::Message> message)
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.cpp b/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.cpp index 6fb3174..ccbc663 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.cpp
@@ -45,8 +45,8 @@ namespace blink { -V8WorkerGlobalScopeEventListener::V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) - : V8EventListener(listener, isInline, scriptState) +V8WorkerGlobalScopeEventListener::V8WorkerGlobalScopeEventListener(bool isInline, ScriptState* scriptState) + : V8EventListener(isInline, scriptState) { }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.h b/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.h index bc8e7c4..63878d6c 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8WorkerGlobalScopeEventListener.h
@@ -43,13 +43,15 @@ public: static PassRefPtrWillBeRawPtr<V8WorkerGlobalScopeEventListener> create(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) { - return adoptRefWillBeNoop(new V8WorkerGlobalScopeEventListener(listener, isInline, scriptState)); + RefPtrWillBeRawPtr<V8WorkerGlobalScopeEventListener> eventListener = adoptRefWillBeNoop(new V8WorkerGlobalScopeEventListener(isInline, scriptState)); + eventListener->setListenerObject(listener); + return eventListener.release(); } void handleEvent(ScriptState*, Event*) override; protected: - V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, ScriptState*); + V8WorkerGlobalScopeEventListener(bool isInline, ScriptState*); private: v8::Local<v8::Value> callListenerFunction(ScriptState*, v8::Local<v8::Value>, Event*) override;
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp index 0cc9c9b..fb9dc2d2 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -203,6 +203,7 @@ CSSPropertyID resolvedProperty = resolveCSSPropertyID(unresolvedProperty); CSSStyleDeclaration* impl = V8CSSStyleDeclaration::toImpl(info.Holder()); + // TODO(leviw): This API doesn't support custom properties. RefPtrWillBeRawPtr<CSSValue> cssValue = impl->getPropertyCSSValueInternal(resolvedProperty); if (cssValue) { v8SetReturnValueStringOrNull(info, cssValue->cssText(), info.GetIsolate()); @@ -224,7 +225,8 @@ TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, propertyValue, value); ExceptionState exceptionState(ExceptionState::SetterContext, getPropertyName(resolveCSSPropertyID(unresolvedProperty)), "CSSStyleDeclaration", info.Holder(), info.GetIsolate()); - impl->setPropertyInternal(unresolvedProperty, propertyValue, false, exceptionState); + // TODO(leviw): This API doesn't support custom properties. + impl->setPropertyInternal(unresolvedProperty, String(), propertyValue, false, exceptionState); if (exceptionState.throwIfNeeded()) return;
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp index 3b3fc0d..58528e58 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp
@@ -41,10 +41,6 @@ void addEventListenerMethodPrologueCustom(const v8::FunctionCallbackInfo<v8::Value>& info, EventTarget*) { - if (info.Length() < 2) { - UseCounter::countIfNotPrivateScript(info.GetIsolate(), callingExecutionContext(info.GetIsolate()), - info.Length() == 0 ? UseCounter::AddEventListenerNoArguments : UseCounter::AddEventListenerOneArgument); - } if (info.Length() >= 3 && info[2]->IsObject()) { UseCounter::countIfNotPrivateScript(info.GetIsolate(), callingExecutionContext(info.GetIsolate()), UseCounter::AddEventListenerThirdArgumentIsObject); @@ -59,10 +55,6 @@ void removeEventListenerMethodPrologueCustom(const v8::FunctionCallbackInfo<v8::Value>& info, EventTarget*) { - if (info.Length() < 2) { - UseCounter::countIfNotPrivateScript(info.GetIsolate(), callingExecutionContext(info.GetIsolate()), - info.Length() == 0 ? UseCounter::RemoveEventListenerNoArguments : UseCounter::RemoveEventListenerOneArgument); - } if (info.Length() >= 3 && info[2]->IsObject()) { UseCounter::countIfNotPrivateScript(info.GetIsolate(), callingExecutionContext(info.GetIsolate()), UseCounter::RemoveEventListenerThirdArgumentIsObject); @@ -80,6 +72,11 @@ void V8EventTarget::addEventListenerMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "addEventListener", "EventTarget", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 2)) { + setMinimumArityTypeError(exceptionState, 2, info.Length()); + exceptionState.throwIfNeeded(); + return; + } EventTarget* impl = V8EventTarget::toImpl(info.Holder()); if (LocalDOMWindow* window = impl->toDOMWindow()) { if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window->frame(), exceptionState)) { @@ -89,22 +86,14 @@ if (!window->document()) return; } - V8StringResource<TreatNullAsNullString> type; + V8StringResource<> type; RefPtrWillBeRawPtr<EventListener> listener; EventListenerOptionsOrBoolean options; { - if (!info[0]->IsUndefined()) { - type = info[0]; - if (!type.prepare()) - return; - } else { - type = nullptr; - } - if (!info[1]->IsUndefined()) { - listener = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[1], false, ListenerFindOrCreate); - } else { - listener = nullptr; - } + type = info[0]; + if (!type.prepare()) + return; + listener = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[1], false, ListenerFindOrCreate); // TODO(dtapuska): This custom binding code can be eliminated once // EventListenerOptions runtime enabled feature is removed. // http://crbug.com/545163 @@ -126,6 +115,11 @@ void V8EventTarget::removeEventListenerMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "removeEventListener", "EventTarget", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 2)) { + setMinimumArityTypeError(exceptionState, 2, info.Length()); + exceptionState.throwIfNeeded(); + return; + } EventTarget* impl = V8EventTarget::toImpl(info.Holder()); if (LocalDOMWindow* window = impl->toDOMWindow()) { if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), callingDOMWindow(info.GetIsolate()), window->frame(), exceptionState)) { @@ -135,22 +129,14 @@ if (!window->document()) return; } - V8StringResource<TreatNullAsNullString> type; + V8StringResource<> type; RefPtrWillBeRawPtr<EventListener> listener; EventListenerOptionsOrBoolean options; { - if (!info[0]->IsUndefined()) { - type = info[0]; - if (!type.prepare()) - return; - } else { - type = nullptr; - } - if (!info[1]->IsUndefined()) { - listener = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[1], false, ListenerFindOnly); - } else { - listener = nullptr; - } + type = info[0]; + if (!type.prepare()) + return; + listener = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[1], false, ListenerFindOnly); // TODO(dtapuska): This custom binding code can be eliminated once // EventListenerOptions runtime enabled feature is removed. // http://crbug.com/545163
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyMetadata.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyMetadata.cpp.tmpl index 9c822ae..cdccc1d3 100644 --- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyMetadata.cpp.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyMetadata.cpp.tmpl
@@ -26,21 +26,28 @@ } {% endfor %} +// There is one more valid property ID than the total count of CSS properties +// because of custom properties. +static const int numValidPropertyIDs = numCSSProperties + 1; + bool CSSPropertyMetadata::isEnabledProperty(CSSPropertyID unresolvedProperty) { CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty); - static BitArray<numCSSProperties>* enabledProperties = 0; + static BitArray<numValidPropertyIDs>* enabledProperties = 0; if (!enabledProperties) { - enabledProperties = new BitArray<numCSSProperties>(true); // All bits sets to 1. + enabledProperties = new BitArray<numValidPropertyIDs>(true); // All bits sets to 1. + static_assert(CSSPropertyVariable == {{first_enum_value - 1}}, "CSSPropertyVariable should directly precede first_enum_value."); + if (!RuntimeEnabledFeatures::cssVariablesEnabled()) + enabledProperties->clear(0); {% for property_id, property in properties.items() if property.runtime_flag %} if (!RuntimeEnabledFeatures::{{property.runtime_flag|lower_first}}Enabled()) - enabledProperties->clear({{property_id}} - {{first_enum_value}}); + enabledProperties->clear({{property_id}} - {{first_enum_value - 1}}); {% endfor %} {% for property_id, property in properties.items() if property.is_internal %} - enabledProperties->clear({{property_id}} - {{first_enum_value}}); + enabledProperties->clear({{property_id}} - {{first_enum_value - 1}}); {% endfor %} } - return enabledProperties->get(property - {{first_enum_value}}); + return enabledProperties->get(property - {{first_enum_value - 1}}); } void CSSPropertyMetadata::filterEnabledCSSPropertiesIntoVector(const CSSPropertyID* properties, size_t propertyCount, Vector<CSSPropertyID>& outVector)
diff --git a/third_party/WebKit/Source/core/animation/IntegerOptionalIntegerSVGInterpolation.cpp b/third_party/WebKit/Source/core/animation/IntegerOptionalIntegerSVGInterpolation.cpp deleted file mode 100644 index 095159d..0000000 --- a/third_party/WebKit/Source/core/animation/IntegerOptionalIntegerSVGInterpolation.cpp +++ /dev/null
@@ -1,40 +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 "config.h" -#include "core/animation/IntegerOptionalIntegerSVGInterpolation.h" - -#include "core/SVGNames.h" - -namespace blink { - -namespace { - -// For order, the values must be integers greater than zero. -// For filterRes, negative values are an error. Zero values disable rendering of the element which referenced the filter. -PassRefPtrWillBeRawPtr<SVGInteger> toPositiveInteger(const InterpolableValue* number, int min) -{ - return SVGInteger::create(clampTo<int>(roundf(toInterpolableNumber(number)->value()), min)); -} - -} // namespace - -PassOwnPtr<InterpolableValue> IntegerOptionalIntegerSVGInterpolation::toInterpolableValue(SVGPropertyBase* value) -{ - RefPtrWillBeRawPtr<SVGIntegerOptionalInteger> integerOptionalInteger = toSVGIntegerOptionalInteger(value); - OwnPtr<InterpolableList> result = InterpolableList::create(2); - result->set(0, InterpolableNumber::create(integerOptionalInteger->firstInteger()->value())); - result->set(1, InterpolableNumber::create(integerOptionalInteger->secondInteger()->value())); - return result.release(); -} - -PassRefPtrWillBeRawPtr<SVGIntegerOptionalInteger> IntegerOptionalIntegerSVGInterpolation::fromInterpolableValue(const InterpolableValue& value, int min) -{ - const InterpolableList& list = toInterpolableList(value); - return SVGIntegerOptionalInteger::create( - toPositiveInteger(list.get(0), min), - toPositiveInteger(list.get(1), min)); -} - -}
diff --git a/third_party/WebKit/Source/core/animation/IntegerOptionalIntegerSVGInterpolation.h b/third_party/WebKit/Source/core/animation/IntegerOptionalIntegerSVGInterpolation.h deleted file mode 100644 index 970abcf5b..0000000 --- a/third_party/WebKit/Source/core/animation/IntegerOptionalIntegerSVGInterpolation.h +++ /dev/null
@@ -1,44 +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 IntegerOptionalIntegerSVGInterpolation_h -#define IntegerOptionalIntegerSVGInterpolation_h - -#include "core/animation/SVGInterpolation.h" -#include "core/svg/SVGIntegerOptionalInteger.h" -#include "platform/heap/Handle.h" - -namespace blink { - -class SVGIntegerOptionalInteger; - -class IntegerOptionalIntegerSVGInterpolation : public SVGInterpolation { -public: - static PassRefPtr<IntegerOptionalIntegerSVGInterpolation> create(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute, int min) - { - return adoptRef(new IntegerOptionalIntegerSVGInterpolation(toInterpolableValue(start), toInterpolableValue(end), attribute, min)); - } - - PassRefPtrWillBeRawPtr<SVGPropertyBase> interpolatedValue(SVGElement&) const final - { - return fromInterpolableValue(*m_cachedValue, m_min); - } - -private: - IntegerOptionalIntegerSVGInterpolation(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute, int min) - : SVGInterpolation(start, end, attribute) - , m_min(min) - { - } - - static PassOwnPtr<InterpolableValue> toInterpolableValue(SVGPropertyBase*); - - static PassRefPtrWillBeRawPtr<SVGIntegerOptionalInteger> fromInterpolableValue(const InterpolableValue&, int); - - const int m_min; -}; - -} - -#endif // IntegerOptionalIntegerSVGInterpolation_h
diff --git a/third_party/WebKit/Source/core/animation/NumberOptionalNumberSVGInterpolation.h b/third_party/WebKit/Source/core/animation/NumberOptionalNumberSVGInterpolation.h deleted file mode 100644 index 18b26c6..0000000 --- a/third_party/WebKit/Source/core/animation/NumberOptionalNumberSVGInterpolation.h +++ /dev/null
@@ -1,54 +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 NumberOptionalNumberSVGInterpolation_h -#define NumberOptionalNumberSVGInterpolation_h - -#include "core/animation/SVGInterpolation.h" -#include "core/svg/SVGNumber.h" -#include "core/svg/SVGNumberOptionalNumber.h" - -namespace blink { - -class SVGNumberOptionalNumber; - -class NumberOptionalNumberSVGInterpolation : public SVGInterpolation { -public: - static PassRefPtr<NumberOptionalNumberSVGInterpolation> create(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) - { - return adoptRef(new NumberOptionalNumberSVGInterpolation(toInterpolableValue(start), toInterpolableValue(end), attribute)); - } - - PassRefPtrWillBeRawPtr<SVGPropertyBase> interpolatedValue(SVGElement&) const final - { - return fromInterpolableValue(*m_cachedValue); - } - -private: - NumberOptionalNumberSVGInterpolation(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) - : SVGInterpolation(start, end, attribute) - { - } - - static PassOwnPtr<InterpolableValue> toInterpolableValue(SVGPropertyBase* value) - { - RefPtrWillBeRawPtr<SVGNumberOptionalNumber> numberOptionalNumber = toSVGNumberOptionalNumber(value); - OwnPtr<InterpolableList> result = InterpolableList::create(2); - result->set(0, InterpolableNumber::create(numberOptionalNumber->firstNumber()->value())); - result->set(1, InterpolableNumber::create(numberOptionalNumber->secondNumber()->value())); - return result.release(); - } - - static PassRefPtrWillBeRawPtr<SVGNumberOptionalNumber> fromInterpolableValue(const InterpolableValue& value) - { - const InterpolableList& list = toInterpolableList(value); - return SVGNumberOptionalNumber::create( - SVGNumber::create(toInterpolableNumber(list.get(0))->value()), - SVGNumber::create(toInterpolableNumber(list.get(1))->value())); - } -}; - -} - -#endif // NumberOptionalNumberSVGInterpolation_h
diff --git a/third_party/WebKit/Source/core/animation/RectSVGInterpolation.cpp b/third_party/WebKit/Source/core/animation/RectSVGInterpolation.cpp deleted file mode 100644 index e732c0d..0000000 --- a/third_party/WebKit/Source/core/animation/RectSVGInterpolation.cpp +++ /dev/null
@@ -1,34 +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 "config.h" -#include "core/animation/RectSVGInterpolation.h" - -#include "wtf/StdLibExtras.h" - -namespace blink { - -PassOwnPtr<InterpolableValue> RectSVGInterpolation::toInterpolableValue(SVGPropertyBase* value) -{ - RefPtrWillBeRawPtr<SVGRect> rect = toSVGRect(value); - float element[] = { rect->x(), rect->y(), rect->width(), rect->height() }; - OwnPtr<InterpolableList> result = InterpolableList::create(WTF_ARRAY_LENGTH(element)); - for (size_t i = 0; i < WTF_ARRAY_LENGTH(element); i++) { - result->set(i, InterpolableNumber::create(element[i])); - } - return result.release(); -} - -PassRefPtrWillBeRawPtr<SVGRect> RectSVGInterpolation::fromInterpolableValue(const InterpolableValue& value) -{ - const InterpolableList& list = toInterpolableList(value); - RefPtrWillBeRawPtr<SVGRect> result = SVGRect::create(); - result->setX(toInterpolableNumber(list.get(0))->value()); - result->setY(toInterpolableNumber(list.get(1))->value()); - result->setWidth(toInterpolableNumber(list.get(2))->value()); - result->setHeight(toInterpolableNumber(list.get(3))->value()); - return result; -} - -}
diff --git a/third_party/WebKit/Source/core/animation/RectSVGInterpolation.h b/third_party/WebKit/Source/core/animation/RectSVGInterpolation.h deleted file mode 100644 index b9b9048..0000000 --- a/third_party/WebKit/Source/core/animation/RectSVGInterpolation.h +++ /dev/null
@@ -1,40 +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 RectSVGInterpolation_h -#define RectSVGInterpolation_h - -#include "core/animation/SVGInterpolation.h" -#include "core/svg/SVGRect.h" - -namespace blink { - -class SVGRect; - -class RectSVGInterpolation : public SVGInterpolation { -public: - static PassRefPtr<RectSVGInterpolation> create(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) - { - return adoptRef(new RectSVGInterpolation(toInterpolableValue(start), toInterpolableValue(end), attribute)); - } - - PassRefPtrWillBeRawPtr<SVGPropertyBase> interpolatedValue(SVGElement&) const final - { - return fromInterpolableValue(*m_cachedValue); - } - -private: - RectSVGInterpolation(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) - : SVGInterpolation(start, end, attribute) - { - } - - static PassOwnPtr<InterpolableValue> toInterpolableValue(SVGPropertyBase*); - - static PassRefPtrWillBeRawPtr<SVGRect> fromInterpolableValue(const InterpolableValue&); -}; - -} - -#endif // RectSVGInterpolation_h
diff --git a/third_party/WebKit/Source/core/animation/SVGIntegerOptionalIntegerInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGIntegerOptionalIntegerInterpolationType.cpp new file mode 100644 index 0000000..e250521d --- /dev/null +++ b/third_party/WebKit/Source/core/animation/SVGIntegerOptionalIntegerInterpolationType.cpp
@@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/animation/SVGIntegerOptionalIntegerInterpolationType.h" + +#include "core/animation/InterpolationEnvironment.h" +#include "core/svg/SVGIntegerOptionalInteger.h" + +namespace blink { + +PassOwnPtr<InterpolationValue> SVGIntegerOptionalIntegerInterpolationType::maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const +{ + OwnPtr<InterpolableList> result = InterpolableList::create(2); + result->set(0, InterpolableNumber::create(0)); + result->set(1, InterpolableNumber::create(0)); + return InterpolationValue::create(*this, result.release()); +} + +PassOwnPtr<InterpolationValue> SVGIntegerOptionalIntegerInterpolationType::maybeConvertSVGValue(const SVGPropertyBase& svgValue) const +{ + if (svgValue.type() != AnimatedIntegerOptionalInteger) + return nullptr; + + const SVGIntegerOptionalInteger& integerOptionalInteger = toSVGIntegerOptionalInteger(svgValue); + OwnPtr<InterpolableList> result = InterpolableList::create(2); + result->set(0, InterpolableNumber::create(integerOptionalInteger.firstInteger()->value())); + result->set(1, InterpolableNumber::create(integerOptionalInteger.secondInteger()->value())); + return InterpolationValue::create(*this, result.release()); +} + +static PassRefPtrWillBeRawPtr<SVGInteger> toPositiveInteger(const InterpolableValue* number) +{ + return SVGInteger::create(clampTo<int>(roundf(toInterpolableNumber(number)->value()), 1)); +} + +PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGIntegerOptionalIntegerInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const +{ + const InterpolableList& list = toInterpolableList(interpolableValue); + return SVGIntegerOptionalInteger::create( + toPositiveInteger(list.get(0)), + toPositiveInteger(list.get(1))); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/SVGIntegerOptionalIntegerInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGIntegerOptionalIntegerInterpolationType.h new file mode 100644 index 0000000..8a54f46 --- /dev/null +++ b/third_party/WebKit/Source/core/animation/SVGIntegerOptionalIntegerInterpolationType.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 SVGIntegerOptionalIntegerInterpolationType_h +#define SVGIntegerOptionalIntegerInterpolationType_h + +#include "core/animation/NumberAttributeFunctions.h" +#include "core/animation/SVGInterpolationType.h" + +namespace blink { + +class SVGIntegerOptionalIntegerInterpolationType : public SVGInterpolationType { +public: + SVGIntegerOptionalIntegerInterpolationType(const QualifiedName& attribute) + : SVGInterpolationType(attribute) + { } + +private: + PassOwnPtr<InterpolationValue> maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const final; + PassOwnPtr<InterpolationValue> maybeConvertSVGValue(const SVGPropertyBase& svgValue) const final; + PassRefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*) const final; +}; + +} // namespace blink + +#endif // SVGIntegerOptionalIntegerInterpolationType_h
diff --git a/third_party/WebKit/Source/core/animation/SVGNumberOptionalNumberInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGNumberOptionalNumberInterpolationType.cpp new file mode 100644 index 0000000..4d90fdea --- /dev/null +++ b/third_party/WebKit/Source/core/animation/SVGNumberOptionalNumberInterpolationType.cpp
@@ -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 "config.h" +#include "core/animation/SVGNumberOptionalNumberInterpolationType.h" + +#include "core/animation/InterpolationEnvironment.h" +#include "core/svg/SVGNumberOptionalNumber.h" + +namespace blink { + +PassOwnPtr<InterpolationValue> SVGNumberOptionalNumberInterpolationType::maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const +{ + OwnPtr<InterpolableList> result = InterpolableList::create(2); + result->set(0, InterpolableNumber::create(0)); + result->set(1, InterpolableNumber::create(0)); + return InterpolationValue::create(*this, result.release()); +} + +PassOwnPtr<InterpolationValue> SVGNumberOptionalNumberInterpolationType::maybeConvertSVGValue(const SVGPropertyBase& svgValue) const +{ + if (svgValue.type() != AnimatedNumberOptionalNumber) + return nullptr; + + const SVGNumberOptionalNumber& numberOptionalNumber = toSVGNumberOptionalNumber(svgValue); + OwnPtr<InterpolableList> result = InterpolableList::create(2); + result->set(0, InterpolableNumber::create(numberOptionalNumber.firstNumber()->value())); + result->set(1, InterpolableNumber::create(numberOptionalNumber.secondNumber()->value())); + return InterpolationValue::create(*this, result.release()); +} + +PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGNumberOptionalNumberInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const +{ + const InterpolableList& list = toInterpolableList(interpolableValue); + return SVGNumberOptionalNumber::create( + SVGNumber::create(toInterpolableNumber(list.get(0))->value()), + SVGNumber::create(toInterpolableNumber(list.get(1))->value())); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/SVGNumberOptionalNumberInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGNumberOptionalNumberInterpolationType.h new file mode 100644 index 0000000..fe75895 --- /dev/null +++ b/third_party/WebKit/Source/core/animation/SVGNumberOptionalNumberInterpolationType.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 SVGNumberOptionalNumberInterpolationType_h +#define SVGNumberOptionalNumberInterpolationType_h + +#include "core/animation/NumberAttributeFunctions.h" +#include "core/animation/SVGInterpolationType.h" + +namespace blink { + +class SVGNumberOptionalNumberInterpolationType : public SVGInterpolationType { +public: + SVGNumberOptionalNumberInterpolationType(const QualifiedName& attribute) + : SVGInterpolationType(attribute) + { } + +private: + PassOwnPtr<InterpolationValue> maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const final; + PassOwnPtr<InterpolationValue> maybeConvertSVGValue(const SVGPropertyBase& svgValue) const final; + PassRefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*) const final; +}; + +} // namespace blink + +#endif // SVGNumberOptionalNumberInterpolationType_h
diff --git a/third_party/WebKit/Source/core/animation/SVGRectInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGRectInterpolationType.cpp new file mode 100644 index 0000000..2cad227a --- /dev/null +++ b/third_party/WebKit/Source/core/animation/SVGRectInterpolationType.cpp
@@ -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 "config.h" +#include "core/animation/SVGRectInterpolationType.h" + +#include "core/animation/InterpolationEnvironment.h" +#include "core/animation/StringKeyframe.h" +#include "core/svg/SVGRect.h" +#include "wtf/StdLibExtras.h" + +namespace blink { + +enum RectComponentIndex { + RectX, + RectY, + RectWidth, + RectHeight, + RectComponentIndexCount, +}; + +PassOwnPtr<InterpolationValue> SVGRectInterpolationType::maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const +{ + OwnPtr<InterpolableList> result = InterpolableList::create(RectComponentIndexCount); + for (size_t i = 0; i < RectComponentIndexCount; i++) + result->set(i, InterpolableNumber::create(0)); + return InterpolationValue::create(*this, result.release()); +} + +PassOwnPtr<InterpolationValue> SVGRectInterpolationType::maybeConvertSVGValue(const SVGPropertyBase& svgValue) const +{ + if (svgValue.type() != AnimatedRect) + return nullptr; + + const SVGRect& rect = toSVGRect(svgValue); + OwnPtr<InterpolableList> result = InterpolableList::create(RectComponentIndexCount); + result->set(RectX, InterpolableNumber::create(rect.x())); + result->set(RectY, InterpolableNumber::create(rect.y())); + result->set(RectWidth, InterpolableNumber::create(rect.width())); + result->set(RectHeight, InterpolableNumber::create(rect.height())); + return InterpolationValue::create(*this, result.release()); +} + +PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGRectInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const +{ + const InterpolableList& list = toInterpolableList(interpolableValue); + RefPtrWillBeRawPtr<SVGRect> result = SVGRect::create(); + result->setX(toInterpolableNumber(list.get(RectX))->value()); + result->setY(toInterpolableNumber(list.get(RectY))->value()); + result->setWidth(toInterpolableNumber(list.get(RectWidth))->value()); + result->setHeight(toInterpolableNumber(list.get(RectHeight))->value()); + return result; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/SVGRectInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGRectInterpolationType.h new file mode 100644 index 0000000..e46f94b --- /dev/null +++ b/third_party/WebKit/Source/core/animation/SVGRectInterpolationType.h
@@ -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. + +#ifndef SVGRectInterpolationType_h +#define SVGRectInterpolationType_h + +#include "core/animation/SVGInterpolationType.h" + +namespace blink { + +class SVGRectInterpolationType : public SVGInterpolationType { +public: + SVGRectInterpolationType(const QualifiedName& attribute) + : SVGInterpolationType(attribute) + { } + +private: + PassOwnPtr<InterpolationValue> maybeConvertNeutral(const UnderlyingValue&, ConversionCheckers&) const final; + PassOwnPtr<InterpolationValue> maybeConvertSVGValue(const SVGPropertyBase& svgValue) const final; + PassRefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*) const final; +}; + +} // namespace blink + +#endif // SVGRectInterpolationType_h
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp index 200d690a..ddc96968 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
@@ -21,7 +21,6 @@ #include "core/animation/DoubleStyleInterpolation.h" #include "core/animation/FilterStyleInterpolation.h" #include "core/animation/ImageSliceStyleInterpolation.h" -#include "core/animation/IntegerOptionalIntegerSVGInterpolation.h" #include "core/animation/InterpolationType.h" #include "core/animation/InvalidatableInterpolation.h" #include "core/animation/LegacyStyleInterpolation.h" @@ -31,14 +30,15 @@ #include "core/animation/LengthStyleInterpolation.h" #include "core/animation/ListSVGInterpolation.h" #include "core/animation/ListStyleInterpolation.h" -#include "core/animation/NumberOptionalNumberSVGInterpolation.h" #include "core/animation/NumberSVGInterpolation.h" #include "core/animation/PathSVGInterpolation.h" -#include "core/animation/RectSVGInterpolation.h" #include "core/animation/SVGAngleInterpolationType.h" #include "core/animation/SVGIntegerInterpolationType.h" +#include "core/animation/SVGIntegerOptionalIntegerInterpolationType.h" #include "core/animation/SVGNumberInterpolationType.h" +#include "core/animation/SVGNumberOptionalNumberInterpolationType.h" #include "core/animation/SVGPointListInterpolationType.h" +#include "core/animation/SVGRectInterpolationType.h" #include "core/animation/SVGStrokeDasharrayStyleInterpolation.h" #include "core/animation/SVGValueInterpolationType.h" #include "core/animation/TransformSVGInterpolation.h" @@ -272,6 +272,8 @@ || attribute == SVGNames::targetXAttr || attribute == SVGNames::targetYAttr) { applicableTypes->append(adoptPtr(new SVGIntegerInterpolationType(attribute))); + } else if (attribute == SVGNames::orderAttr) { + applicableTypes->append(adoptPtr(new SVGIntegerOptionalIntegerInterpolationType(attribute))); } else if (attribute == SVGNames::amplitudeAttr || attribute == SVGNames::azimuthAttr || attribute == SVGNames::biasAttr @@ -298,8 +300,15 @@ || attribute == SVGNames::surfaceScaleAttr || attribute == SVGNames::zAttr) { applicableTypes->append(adoptPtr(new SVGNumberInterpolationType(attribute))); + } else if (attribute == SVGNames::baseFrequencyAttr + || attribute == SVGNames::kernelUnitLengthAttr + || attribute == SVGNames::radiusAttr + || attribute == SVGNames::stdDeviationAttr) { + applicableTypes->append(adoptPtr(new SVGNumberOptionalNumberInterpolationType(attribute))); } else if (attribute == SVGNames::pointsAttr) { applicableTypes->append(adoptPtr(new SVGPointListInterpolationType(attribute))); + } else if (attribute == SVGNames::viewBoxAttr) { + applicableTypes->append(adoptPtr(new SVGRectInterpolationType(attribute))); } else if (attribute == HTMLNames::classAttr || attribute == SVGNames::clipPathUnitsAttr || attribute == SVGNames::edgeModeAttr @@ -559,25 +568,17 @@ RefPtr<Interpolation> interpolation = nullptr; ASSERT(fromValue->type() == toValue->type()); switch (fromValue->type()) { - case AnimatedIntegerOptionalInteger: { - int min = &attribute->attributeName() == &SVGNames::orderAttr ? 1 : 0; - return IntegerOptionalIntegerSVGInterpolation::create(fromValue, toValue, attribute, min); - } case AnimatedLength: return LengthSVGInterpolation::create(fromValue, toValue, attribute); case AnimatedLengthList: interpolation = ListSVGInterpolation<LengthSVGInterpolation>::maybeCreate(fromValue, toValue, attribute); break; - case AnimatedNumberOptionalNumber: - return NumberOptionalNumberSVGInterpolation::create(fromValue, toValue, attribute); case AnimatedNumberList: interpolation = ListSVGInterpolation<NumberSVGInterpolation>::maybeCreate(fromValue, toValue, attribute); break; case AnimatedPath: interpolation = PathSVGInterpolation::maybeCreate(fromValue, toValue, attribute); break; - case AnimatedRect: - return RectSVGInterpolation::create(fromValue, toValue, attribute); case AnimatedTransformList: interpolation = ListSVGInterpolation<TransformSVGInterpolation>::maybeCreate(fromValue, toValue, attribute); break; @@ -585,8 +586,11 @@ // Handled by SVGInterpolationTypes. case AnimatedAngle: case AnimatedInteger: + case AnimatedIntegerOptionalInteger: case AnimatedNumber: + case AnimatedNumberOptionalNumber: case AnimatedPoints: + case AnimatedRect: ASSERT_NOT_REACHED(); // Fallthrough.
diff --git a/third_party/WebKit/Source/core/core.gyp b/third_party/WebKit/Source/core/core.gyp index 9eb50c8..a72f8dc 100644 --- a/third_party/WebKit/Source/core/core.gyp +++ b/third_party/WebKit/Source/core/core.gyp
@@ -706,6 +706,7 @@ '../platform/platform_generated.gyp:make_platform_generated', '../wtf/wtf.gyp:wtf', + '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/gin/gin.gyp:gin', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/third_party/libxml/libxml.gyp:libxml', @@ -720,6 +721,7 @@ 'export_dependent_settings': [ '../platform/blink_platform.gyp:blink_platform', '../wtf/wtf.gyp:wtf', + '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/third_party/npapi/npapi.gyp:npapi', '<(DEPTH)/third_party/qcms/qcms.gyp:qcms',
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index eec56829..ce7ef24 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi
@@ -868,8 +868,6 @@ 'animation/ImageSliceStyleInterpolation.h', 'animation/InertEffect.cpp', 'animation/InertEffect.h', - 'animation/IntegerOptionalIntegerSVGInterpolation.cpp', - 'animation/IntegerOptionalIntegerSVGInterpolation.h', 'animation/IntegerSVGInterpolation.h', 'animation/InterpolableValue.cpp', 'animation/InterpolableValue.h', @@ -898,7 +896,6 @@ 'animation/ListInterpolationFunctions.h', 'animation/NonInterpolableValue.h', 'animation/NumberAttributeFunctions.h', - 'animation/NumberOptionalNumberSVGInterpolation.h', 'animation/NumberPropertyFunctions.cpp', 'animation/NumberPropertyFunctions.h', 'animation/NumberSVGInterpolation.cpp', @@ -908,21 +905,25 @@ 'animation/PrimitiveInterpolation.h', 'animation/PropertyHandle.cpp', 'animation/PropertyHandle.h', - 'animation/RectSVGInterpolation.cpp', - 'animation/RectSVGInterpolation.h', 'animation/SVGAngleInterpolationType.cpp', 'animation/SVGAngleInterpolationType.h', 'animation/SVGIntegerInterpolationType.cpp', 'animation/SVGIntegerInterpolationType.h', + 'animation/SVGIntegerOptionalIntegerInterpolationType.cpp', + 'animation/SVGIntegerOptionalIntegerInterpolationType.h', 'animation/SVGInterpolation.cpp', 'animation/SVGInterpolation.h', 'animation/SVGInterpolationType.cpp', 'animation/SVGInterpolationType.h', 'animation/SVGNumberInterpolationType.cpp', 'animation/SVGNumberInterpolationType.h', + 'animation/SVGNumberOptionalNumberInterpolationType.cpp', + 'animation/SVGNumberOptionalNumberInterpolationType.h', 'animation/SVGPointListInterpolationType.cpp', 'animation/SVGPointListInterpolationType.h', 'animation/SVGStrokeDasharrayStyleInterpolation.cpp', + 'animation/SVGRectInterpolationType.cpp', + 'animation/SVGRectInterpolationType.h', 'animation/SVGStrokeDasharrayStyleInterpolation.h', 'animation/SVGValueInterpolationType.cpp', 'animation/SVGValueInterpolationType.h', @@ -2013,6 +2014,8 @@ 'paint/PaintPhase.h', 'paint/PaintPropertyTreeBuilder.cpp', 'paint/PaintPropertyTreeBuilder.h', + 'paint/PaintTiming.cpp', + 'paint/PaintTiming.h', 'paint/PartPainter.cpp', 'paint/PartPainter.h', 'paint/ReplacedPainter.cpp', @@ -3419,13 +3422,13 @@ 'svg/SVGPathElement.h', 'svg/SVGPathParser.cpp', 'svg/SVGPathParser.h', + 'svg/SVGPathQuery.cpp', + 'svg/SVGPathQuery.h', 'svg/SVGPathSource.h', 'svg/SVGPathStringBuilder.cpp', 'svg/SVGPathStringBuilder.h', 'svg/SVGPathStringSource.cpp', 'svg/SVGPathStringSource.h', - 'svg/SVGPathTraversalStateBuilder.cpp', - 'svg/SVGPathTraversalStateBuilder.h', 'svg/SVGPathUtilities.cpp', 'svg/SVGPathUtilities.h', 'svg/SVGPatternElement.cpp',
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp index 1efc3a64..2b1a7d97 100644 --- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp
@@ -677,8 +677,9 @@ return getPropertyValue(propertyID); } -void CSSComputedStyleDeclaration::setPropertyInternal(CSSPropertyID id, const String&, bool, ExceptionState& exceptionState) +void CSSComputedStyleDeclaration::setPropertyInternal(CSSPropertyID id, const String&, const String&, bool, ExceptionState& exceptionState) { + // TODO(leviw): This code is currently unreachable, but shouldn't be. exceptionState.throwDOMException(NoModificationAllowedError, "These styles are computed, and therefore the '" + getPropertyNameString(id) + "' property is read-only."); }
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h index 6fc6e4f..488584ce 100644 --- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h +++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h
@@ -97,7 +97,7 @@ void setCSSText(const String&, ExceptionState&) override; PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) override; String getPropertyValueInternal(CSSPropertyID) override; - void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&) override; + void setPropertyInternal(CSSPropertyID, const String& customPropertyName, const String& value, bool important, ExceptionState&) override; bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const override;
diff --git a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.cpp b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.cpp index be7770eb..c6f2b96 100644 --- a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.cpp
@@ -5,6 +5,8 @@ #include "config.h" #include "core/css/CSSCustomPropertyDeclaration.h" +#include "core/css/parser/CSSParserTokenRange.h" + namespace blink { DEFINE_TRACE_AFTER_DISPATCH(CSSCustomPropertyDeclaration) @@ -12,4 +14,9 @@ CSSValue::traceAfterDispatch(visitor); } +String CSSCustomPropertyDeclaration::customCSSText() const +{ + return m_value->tokenRange().serialize(); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h index 01c959bd..22dc8cd 100644 --- a/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h +++ b/third_party/WebKit/Source/core/css/CSSCustomPropertyDeclaration.h
@@ -27,6 +27,7 @@ const AtomicString& name() const { return m_name; } CSSVariableData* value() const { return m_value.get(); } CSSValueID id() const { return m_valueId; } + String customCSSText() const; bool equals(const CSSCustomPropertyDeclaration& other) const { return this == &other; }
diff --git a/third_party/WebKit/Source/core/css/CSSFontFace.cpp b/third_party/WebKit/Source/core/css/CSSFontFace.cpp index 838fb993..41e7f8d6f 100644 --- a/third_party/WebKit/Source/core/css/CSSFontFace.cpp +++ b/third_party/WebKit/Source/core/css/CSSFontFace.cpp
@@ -63,6 +63,9 @@ if (loadStatus() == FontFace::Loading) { if (source->isValid()) { setLoadStatus(FontFace::Loaded); + } else if (source->displayPeriod() == RemoteFontFaceSource::FailurePeriod) { + m_sources.clear(); + setLoadStatus(FontFace::Error); } else { m_sources.removeFirst(); load(); @@ -70,15 +73,15 @@ } if (m_segmentedFontFace) - m_segmentedFontFace->fontLoaded(this); + m_segmentedFontFace->fontFaceInvalidated(); } -void CSSFontFace::fontLoadWaitLimitExceeded(RemoteFontFaceSource* source) +void CSSFontFace::didBecomeVisibleFallback(RemoteFontFaceSource* source) { if (!isValid() || source != m_sources.first()) return; if (m_segmentedFontFace) - m_segmentedFontFace->fontLoadWaitLimitExceeded(this); + m_segmentedFontFace->fontFaceInvalidated(); } PassRefPtr<SimpleFontData> CSSFontFace::getFontData(const FontDescription& fontDescription)
diff --git a/third_party/WebKit/Source/core/css/CSSFontFace.h b/third_party/WebKit/Source/core/css/CSSFontFace.h index 0a87261..000bf6e 100644 --- a/third_party/WebKit/Source/core/css/CSSFontFace.h +++ b/third_party/WebKit/Source/core/css/CSSFontFace.h
@@ -70,7 +70,7 @@ void didBeginLoad(); void fontLoaded(RemoteFontFaceSource*); - void fontLoadWaitLimitExceeded(RemoteFontFaceSource*); + void didBecomeVisibleFallback(RemoteFontFaceSource*); PassRefPtr<SimpleFontData> getFontData(const FontDescription&);
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp b/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp index f22770b3..35c241c 100644 --- a/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp
@@ -440,10 +440,10 @@ } LengthUnitType lengthType; - if (unitTypeToLengthUnitType(type(), lengthType)) { - lengthArray.at(lengthType) += m_value.num * conversionToCanonicalUnitsScaleFactor(type()) * multiplier; - lengthTypeArray.set(lengthType); - } + bool conversionSuccess = unitTypeToLengthUnitType(type(), lengthType); + ASSERT_UNUSED(conversionSuccess, conversionSuccess); + lengthArray.at(lengthType) += m_value.num * conversionToCanonicalUnitsScaleFactor(type()) * multiplier; + lengthTypeArray.set(lengthType); } void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray& lengthArray, double multiplier) const
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in index 8bd4e1a1..3555ea1 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.in +++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -430,6 +430,7 @@ // TODO(timloh): This seems wrong, most of these shouldn't reach the StyleBuilder all builder_skip +font-display builder_skip, runtime_flag=CSSFontDisplay max-zoom builder_skip min-zoom builder_skip orientation builder_skip
diff --git a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp index 9a222cb..4907f87 100644 --- a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp +++ b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp
@@ -72,12 +72,7 @@ return false; } -void CSSSegmentedFontFace::fontLoaded(CSSFontFace*) -{ - pruneTable(); -} - -void CSSSegmentedFontFace::fontLoadWaitLimitExceeded(CSSFontFace*) +void CSSSegmentedFontFace::fontFaceInvalidated() { pruneTable(); }
diff --git a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h index 25e25956..dba289f2b 100644 --- a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h +++ b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h
@@ -56,8 +56,9 @@ CSSFontSelector* fontSelector() const { return m_fontSelector; } FontTraits traits() const { return m_traits; } - void fontLoaded(CSSFontFace*); - void fontLoadWaitLimitExceeded(CSSFontFace*); + // Called when status of a FontFace has changed (e.g. loaded or timed out) + // so cached FontData must be discarded. + void fontFaceInvalidated(); void addFontFace(PassRefPtrWillBeRawPtr<FontFace>, bool cssConnected); void removeFontFace(PassRefPtrWillBeRawPtr<FontFace>);
diff --git a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h index 26ac96d..808fc944 100644 --- a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h +++ b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h
@@ -53,7 +53,7 @@ } void setCSSFloat(const String& value, ExceptionState& exceptionState) { - setPropertyInternal(CSSPropertyFloat, value, false, exceptionState); + setPropertyInternal(CSSPropertyFloat, String(), value, false, exceptionState); } virtual String cssText() const = 0; virtual void setCSSText(const String&, ExceptionState&) = 0; @@ -71,7 +71,7 @@ // The CSSValue returned by this function should not be exposed to the web as it may be used by multiple documents at the same time. virtual PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) = 0; virtual String getPropertyValueInternal(CSSPropertyID) = 0; - virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&) = 0; + virtual void setPropertyInternal(CSSPropertyID, const String& propertyValue, const String& value, bool important, ExceptionState&) = 0; virtual bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const = 0; virtual CSSStyleSheet* parentStyleSheet() const { return 0; }
diff --git a/third_party/WebKit/Source/core/css/CSSValue.cpp b/third_party/WebKit/Source/core/css/CSSValue.cpp index dcc6bd1..462a560 100644 --- a/third_party/WebKit/Source/core/css/CSSValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSValue.cpp
@@ -261,8 +261,7 @@ case VariableReferenceClass: return toCSSVariableReferenceValue(this)->customCSSText(); case CustomPropertyDeclarationClass: - // TODO(leviw): We don't allow custom properties in CSSOM yet - ASSERT_NOT_REACHED(); + return toCSSCustomPropertyDeclaration(this)->customCSSText(); } ASSERT_NOT_REACHED(); return String();
diff --git a/third_party/WebKit/Source/core/css/CSSValueKeywords.in b/third_party/WebKit/Source/core/css/CSSValueKeywords.in index 8d673ee..0020213 100644 --- a/third_party/WebKit/Source/core/css/CSSValueKeywords.in +++ b/third_party/WebKit/Source/core/css/CSSValueKeywords.in
@@ -121,6 +121,15 @@ -webkit-pictograph // +// font-display +// +//auto +//block +swap +fallback +optional + +// // // *-color //
diff --git a/third_party/WebKit/Source/core/css/FontFace.cpp b/third_party/WebKit/Source/core/css/FontFace.cpp index 6aedc0b..90bb5a9 100644 --- a/third_party/WebKit/Source/core/css/FontFace.cpp +++ b/third_party/WebKit/Source/core/css/FontFace.cpp
@@ -128,6 +128,7 @@ && fontFace->setPropertyFromStyle(properties, CSSPropertyUnicodeRange) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontVariant) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontFeatureSettings) + && fontFace->setPropertyFromStyle(properties, CSSPropertyFontDisplay) && !fontFace->family().isEmpty() && fontFace->traits().bitfield()) { fontFace->initCSSFontFace(document, src); @@ -264,6 +265,9 @@ case CSSPropertyFontFeatureSettings: m_featureSettings = value; break; + case CSSPropertyFontDisplay: + m_display = value; + break; default: ASSERT_NOT_REACHED(); return false; @@ -528,6 +532,27 @@ return FontTraits(style, variant, weight, stretch); } +static FontDisplay CSSValueToFontDisplay(CSSValue* value) +{ + if (value && value->isPrimitiveValue()) { + switch (toCSSPrimitiveValue(value)->getValueID()) { + case CSSValueAuto: + return FontDisplayAuto; + case CSSValueBlock: + return FontDisplayBlock; + case CSSValueSwap: + return FontDisplaySwap; + case CSSValueFallback: + return FontDisplayFallback; + case CSSValueOptional: + return FontDisplayOptional; + default: + break; + } + } + return FontDisplayAuto; +} + static PassOwnPtrWillBeRawPtr<CSSFontFace> createCSSFontFace(FontFace* fontFace, CSSValue* unicodeRange) { Vector<CSSFontFace::UnicodeRange> ranges; @@ -566,7 +591,7 @@ FontResource* fetched = item->fetch(document); if (fetched) { FontLoader* fontLoader = document->styleEngine().fontSelector()->fontLoader(); - source = adoptPtrWillBeNoop(new RemoteFontFaceSource(fetched, fontLoader)); + source = adoptPtrWillBeNoop(new RemoteFontFaceSource(fetched, fontLoader, CSSValueToFontDisplay(m_display.get()))); } } } else { @@ -601,6 +626,7 @@ visitor->trace(m_unicodeRange); visitor->trace(m_variant); visitor->trace(m_featureSettings); + visitor->trace(m_display); visitor->trace(m_error); visitor->trace(m_loadedProperty); visitor->trace(m_cssFontFace);
diff --git a/third_party/WebKit/Source/core/css/FontFace.h b/third_party/WebKit/Source/core/css/FontFace.h index d0f5d4b..875761ca 100644 --- a/third_party/WebKit/Source/core/css/FontFace.h +++ b/third_party/WebKit/Source/core/css/FontFace.h
@@ -139,6 +139,7 @@ RefPtrWillBeMember<CSSValue> m_unicodeRange; RefPtrWillBeMember<CSSValue> m_variant; RefPtrWillBeMember<CSSValue> m_featureSettings; + RefPtrWillBeMember<CSSValue> m_display; LoadStatus m_status; PersistentWillBeMember<DOMException> m_error;
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp index 3abfbc33..21995497 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
@@ -24,9 +24,11 @@ #include "bindings/core/v8/ExceptionState.h" #include "core/HTMLNames.h" +#include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSStyleSheet.h" #include "core/css/StylePropertySet.h" +#include "core/css/parser/CSSVariableParser.h" #include "core/dom/Element.h" #include "core/dom/MutationObserverInterestGroup.h" #include "core/dom/MutationRecord.h" @@ -150,7 +152,10 @@ { if (i >= propertySet().propertyCount()) return ""; - return getPropertyName(propertySet().propertyAt(i).id()); + StylePropertySet::PropertyReference property = propertySet().propertyAt(i); + if (RuntimeEnabledFeatures::cssVariablesEnabled() && property.id() == CSSPropertyVariable) + return toCSSCustomPropertyDeclaration(property.value())->name(); + return getPropertyName(property.id()); } String AbstractPropertySetCSSStyleDeclaration::cssText() const @@ -170,25 +175,36 @@ mutationScope.enqueueMutationRecord(); } -String AbstractPropertySetCSSStyleDeclaration::getPropertyValue(const String &propertyName) +String AbstractPropertySetCSSStyleDeclaration::getPropertyValue(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); - if (!propertyID) - return String(); + if (!propertyID) { + if (!RuntimeEnabledFeatures::cssVariablesEnabled() || !CSSVariableParser::isValidVariableName(propertyName)) + return String(); + return propertySet().getPropertyValue(AtomicString(propertyName)); + } return propertySet().getPropertyValue(propertyID); } String AbstractPropertySetCSSStyleDeclaration::getPropertyPriority(const String& propertyName) { + bool important = false; CSSPropertyID propertyID = cssPropertyID(propertyName); - if (!propertyID) - return String(); - return propertySet().propertyIsImportant(propertyID) ? "important" : ""; + if (!propertyID) { + if (!RuntimeEnabledFeatures::cssVariablesEnabled() || !CSSVariableParser::isValidVariableName(propertyName)) + return String(); + important = propertySet().propertyIsImportant(AtomicString(propertyName)); + } else { + important = propertySet().propertyIsImportant(propertyID); + } + return important ? "important" : ""; } String AbstractPropertySetCSSStyleDeclaration::getPropertyShorthand(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); + + // Custom properties don't have shorthands, so we can ignore them here. if (!propertyID) return String(); CSSPropertyID shorthandID = propertySet().getPropertyShorthand(propertyID); @@ -200,6 +216,8 @@ bool AbstractPropertySetCSSStyleDeclaration::isPropertyImplicit(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); + + // Custom properties don't have shorthands, so we can ignore them here. if (!propertyID) return false; return propertySet().isPropertyImplicit(propertyID); @@ -208,27 +226,37 @@ void AbstractPropertySetCSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState& exceptionState) { CSSPropertyID propertyID = unresolvedCSSPropertyID(propertyName); - if (!propertyID) - return; + if (!propertyID) { + if (!RuntimeEnabledFeatures::cssVariablesEnabled() || !CSSVariableParser::isValidVariableName(propertyName)) + return; + propertyID = CSSPropertyVariable; + } bool important = equalIgnoringCase(priority, "important"); if (!important && !priority.isEmpty()) return; - setPropertyInternal(propertyID, value, important, exceptionState); + setPropertyInternal(propertyID, propertyName, value, important, exceptionState); } String AbstractPropertySetCSSStyleDeclaration::removeProperty(const String& propertyName, ExceptionState& exceptionState) { - StyleAttributeMutationScope mutationScope(this); CSSPropertyID propertyID = cssPropertyID(propertyName); - if (!propertyID) - return String(); + if (!propertyID) { + if (!RuntimeEnabledFeatures::cssVariablesEnabled() || !CSSVariableParser::isValidVariableName(propertyName)) + return String(); + propertyID = CSSPropertyVariable; + } + StyleAttributeMutationScope mutationScope(this); willMutate(); String result; - bool changed = propertySet().removeProperty(propertyID, &result); + bool changed = false; + if (propertyID == CSSPropertyVariable) + changed = propertySet().removeProperty(AtomicString(propertyName), &result); + else + changed = propertySet().removeProperty(propertyID, &result); didMutate(changed ? PropertyChanged : NoChanges); @@ -247,12 +275,16 @@ return propertySet().getPropertyValue(propertyID); } -void AbstractPropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID unresolvedProperty, const String& value, bool important, ExceptionState&) +void AbstractPropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID unresolvedProperty, const String& customPropertyName, const String& value, bool important, ExceptionState&) { StyleAttributeMutationScope mutationScope(this); willMutate(); - bool changed = propertySet().setProperty(unresolvedProperty, value, important, contextStyleSheet()); + bool changed = false; + if (unresolvedProperty == CSSPropertyVariable) + changed = propertySet().setProperty(AtomicString(customPropertyName), value, important, contextStyleSheet()); + else + changed = propertySet().setProperty(unresolvedProperty, value, important, contextStyleSheet()); didMutate(changed ? PropertyChanged : NoChanges);
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h index c25c05af..5018599a 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h
@@ -62,7 +62,7 @@ void setCSSText(const String&, ExceptionState&) final; PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) final; String getPropertyValueInternal(CSSPropertyID) final; - void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&) final; + void setPropertyInternal(CSSPropertyID, const String& customPropertyName, const String& value, bool important, ExceptionState&) final; bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const final;
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp index 6f68e61..49a7e1a 100644 --- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp +++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
@@ -16,9 +16,11 @@ namespace blink { -RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, PassRefPtrWillBeRawPtr<FontLoader> fontLoader) +RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, PassRefPtrWillBeRawPtr<FontLoader> fontLoader, FontDisplay display) : m_font(font) , m_fontLoader(fontLoader) + , m_display(display) + , m_period(display == FontDisplaySwap ? SwapPeriod : BlockPeriod) { m_font->addClient(this); } @@ -80,24 +82,50 @@ } } -void RemoteFontFaceSource::fontLoadWaitLimitExceeded(FontResource*) +void RemoteFontFaceSource::fontLoadShortLimitExceeded(FontResource*) { + if (m_display == FontDisplayFallback) + switchToSwapPeriod(); + else if (m_display == FontDisplayOptional) + switchToFailurePeriod(); +} + +void RemoteFontFaceSource::fontLoadLongLimitExceeded(FontResource*) +{ + if (m_display == FontDisplayAuto || m_display == FontDisplayBlock) + switchToSwapPeriod(); + else if (m_display == FontDisplayFallback) + switchToFailurePeriod(); +} + +void RemoteFontFaceSource::switchToSwapPeriod() +{ + ASSERT(m_period == BlockPeriod); + m_period = SwapPeriod; + pruneTable(); if (m_face) { m_fontLoader->fontFaceInvalidated(); - m_face->fontLoadWaitLimitExceeded(this); + m_face->didBecomeVisibleFallback(this); } m_histograms.recordFallbackTime(m_font.get()); } +void RemoteFontFaceSource::switchToFailurePeriod() +{ + if (m_period == BlockPeriod) + switchToSwapPeriod(); + ASSERT(m_period == SwapPeriod); + m_period = FailurePeriod; +} + PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescription& fontDescription) { if (!isLoaded()) return createLoadingFallbackFontData(fontDescription); - // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef. - if (!m_font->ensureCustomFontData()) + if (!m_font->ensureCustomFontData() || m_period == FailurePeriod) return nullptr; m_histograms.recordFallbackTime(m_font.get()); @@ -117,7 +145,7 @@ ASSERT_NOT_REACHED(); return nullptr; } - RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(this, m_font->exceedsFontLoadWaitLimit() ? CSSCustomFontData::VisibleFallback : CSSCustomFontData::InvisibleFallback); + RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(this, m_period == BlockPeriod ? CSSCustomFontData::InvisibleFallback : CSSCustomFontData::VisibleFallback); return SimpleFontData::create(temporaryFont->platformData(), cssFontData); }
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h index 8f2ed11..1d6eb55c 100644 --- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h +++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h
@@ -14,21 +14,33 @@ class FontLoader; +enum FontDisplay { + FontDisplayAuto, + FontDisplayBlock, + FontDisplaySwap, + FontDisplayFallback, + FontDisplayOptional +}; + class RemoteFontFaceSource final : public CSSFontFaceSource, public FontResourceClient { public: - explicit RemoteFontFaceSource(FontResource*, PassRefPtrWillBeRawPtr<FontLoader>); + enum DisplayPeriod { BlockPeriod, SwapPeriod, FailurePeriod }; + + explicit RemoteFontFaceSource(FontResource*, PassRefPtrWillBeRawPtr<FontLoader>, FontDisplay); ~RemoteFontFaceSource() override; FontResource* resource() override { return m_font.get(); } bool isLoading() const override; bool isLoaded() const override; bool isValid() const override; + DisplayPeriod displayPeriod() const { return m_period; } void beginLoadIfNeeded() override; void didStartFontLoad(FontResource*) override; void fontLoaded(FontResource*) override; - void fontLoadWaitLimitExceeded(FontResource*) override; + void fontLoadShortLimitExceeded(FontResource*) override; + void fontLoadLongLimitExceeded(FontResource*) override; String debugName() const override { return "RemoteFontFaceSource"; } // For UMA reporting @@ -58,8 +70,13 @@ double m_fallbackPaintTime; }; + void switchToSwapPeriod(); + void switchToFailurePeriod(); + ResourcePtr<FontResource> m_font; RefPtrWillBeMember<FontLoader> m_fontLoader; + const FontDisplay m_display; + DisplayPeriod m_period; FontLoadHistograms m_histograms; };
diff --git a/third_party/WebKit/Source/core/css/RuleFeature.cpp b/third_party/WebKit/Source/core/css/RuleFeature.cpp index 75a438c..b3aea507 100644 --- a/third_party/WebKit/Source/core/css/RuleFeature.cpp +++ b/third_party/WebKit/Source/core/css/RuleFeature.cpp
@@ -608,8 +608,7 @@ invalidationLists.descendants.append(invalidationData->descendants()); } if (invalidationData->siblings()) { - if (element.parentElement()) - TRACE_SCHEDULE_STYLE_INVALIDATION(*element.parentElement(), *invalidationData->siblings(), classChange, className); + TRACE_SCHEDULE_STYLE_INVALIDATION(element, *invalidationData->siblings(), classChange, className); invalidationLists.siblings.append(invalidationData->siblings()); } } @@ -623,8 +622,7 @@ invalidationLists.descendants.append(invalidationData->descendants()); } if (invalidationData->siblings()) { - if (element.parentElement()) - TRACE_SCHEDULE_STYLE_INVALIDATION(*element.parentElement(), *invalidationData->siblings(), idChange, id); + TRACE_SCHEDULE_STYLE_INVALIDATION(element, *invalidationData->siblings(), idChange, id); invalidationLists.siblings.append(invalidationData->siblings()); } } @@ -638,8 +636,7 @@ invalidationLists.descendants.append(invalidationData->descendants()); } if (invalidationData->siblings()) { - if (element.parentElement()) - TRACE_SCHEDULE_STYLE_INVALIDATION(*element.parentElement(), *invalidationData->siblings(), attributeChange, attributeName); + TRACE_SCHEDULE_STYLE_INVALIDATION(element, *invalidationData->siblings(), attributeChange, attributeName); invalidationLists.siblings.append(invalidationData->siblings()); } } @@ -653,8 +650,7 @@ invalidationLists.descendants.append(invalidationData->descendants()); } if (invalidationData->siblings()) { - if (element.parentElement()) - TRACE_SCHEDULE_STYLE_INVALIDATION(*element.parentElement(), *invalidationData->siblings(), pseudoChange, pseudo); + TRACE_SCHEDULE_STYLE_INVALIDATION(element, *invalidationData->siblings(), pseudoChange, pseudo); invalidationLists.siblings.append(invalidationData->siblings()); } }
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp index eb8165d..4f3f20d 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp +++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -25,6 +25,7 @@ #include "core/CSSValueKeywords.h" #include "core/StylePropertyShorthand.h" +#include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSPropertyMetadata.h" #include "core/css/CSSValuePool.h" #include "wtf/BitArray.h" @@ -176,6 +177,22 @@ { } +String StylePropertySerializer::getCustomPropertyText(const PropertyValueForSerializer& property, bool isNotFirstDecl) const +{ + ASSERT(property.id() == CSSPropertyVariable); + StringBuilder result; + if (isNotFirstDecl) + result.append(' '); + const CSSCustomPropertyDeclaration* value = toCSSCustomPropertyDeclaration(property.value()); + result.append(value->name()); + result.appendLiteral(": "); + result.append(value->customCSSText()); + if (property.isImportant()) + result.appendLiteral(" !important"); + result.append(';'); + return result.toString(); +} + String StylePropertySerializer::getPropertyText(CSSPropertyID propertyID, const String& value, bool isImportant, bool isNotFirstDecl) const { StringBuilder result; @@ -343,6 +360,9 @@ case CSSPropertyWebkitMaskOrigin: shorthandPropertyID = CSSPropertyWebkitMask; break; + case CSSPropertyVariable: + result.append(getCustomPropertyText(property, numDecls++)); + continue; case CSSPropertyAll: result.append(getPropertyText(propertyID, property.value()->cssText(), property.isImportant(), numDecls++)); continue;
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.h b/third_party/WebKit/Source/core/css/StylePropertySerializer.h index d032176..b751f0e9 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySerializer.h +++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.h
@@ -89,6 +89,8 @@ bool m_isInherited; }; + String getCustomPropertyText(const PropertyValueForSerializer&, bool isNotFirstDecl) const; + class StylePropertySetForSerializer final { DISALLOW_NEW(); public:
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.cpp b/third_party/WebKit/Source/core/css/StylePropertySet.cpp index 62200c2..32ab3532 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySet.cpp +++ b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
@@ -24,6 +24,7 @@ #include "core/css/StylePropertySet.h" #include "core/StylePropertyShorthand.h" +#include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSPropertyMetadata.h" #include "core/css/CSSValuePool.h" #include "core/css/StylePropertySerializer.h" @@ -103,21 +104,47 @@ #endif } -int ImmutableStylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const +// Convert property into an uint16_t for comparison with metadata's m_propertyID to avoid +// the compiler converting it to an int multiple times in a loop. +static uint16_t getConvertedCSSPropertyID(CSSPropertyID propertyID) { - // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid - // the compiler converting it to an int multiple times in the loop. - uint16_t id = static_cast<uint16_t>(propertyID); + return static_cast<uint16_t>(propertyID); +} + +static uint16_t getConvertedCSSPropertyID(const AtomicString&) +{ + return static_cast<uint16_t>(CSSPropertyVariable); +} + +static bool isPropertyMatch(const StylePropertyMetadata& metadata, const CSSValue&, uint16_t id, CSSPropertyID propertyID) +{ + ASSERT(id == propertyID); + bool result = metadata.m_propertyID == id; + // Only enabled properties should be part of the style. + ASSERT(!result || CSSPropertyMetadata::isEnabledProperty(propertyID)); + return result; +} + +static bool isPropertyMatch(const StylePropertyMetadata& metadata, const CSSValue& value, uint16_t id, const AtomicString& customPropertyName) +{ + ASSERT(id == CSSPropertyVariable); + return metadata.m_propertyID == id + && toCSSCustomPropertyDeclaration(value).name() == customPropertyName; +} + +template<typename T> +int ImmutableStylePropertySet::findPropertyIndex(T property) const +{ + uint16_t id = getConvertedCSSPropertyID(property); for (int n = m_arraySize - 1 ; n >= 0; --n) { - if (metadataArray()[n].m_propertyID == id) { - // Only enabled properties should be part of the style. - ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID)); + if (isPropertyMatch(metadataArray()[n], *valueArray()[n], id, property)) return n; - } } return -1; } +template CORE_EXPORT int ImmutableStylePropertySet::findPropertyIndex(CSSPropertyID) const; +template CORE_EXPORT int ImmutableStylePropertySet::findPropertyIndex(AtomicString) const; DEFINE_TRACE_AFTER_DISPATCH(ImmutableStylePropertySet) { @@ -139,22 +166,38 @@ } } -String StylePropertySet::getPropertyValue(CSSPropertyID propertyID) const +static String serializeShorthand(const StylePropertySet& propertySet, CSSPropertyID propertyID) { - RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(propertyID); - if (value) - return value->cssText(); - - return StylePropertySerializer(*this).getPropertyValue(propertyID); + return StylePropertySerializer(propertySet).getPropertyValue(propertyID); } -PassRefPtrWillBeRawPtr<CSSValue> StylePropertySet::getPropertyCSSValue(CSSPropertyID propertyID) const +static String serializeShorthand(const StylePropertySet&, const AtomicString& customPropertyName) { - int foundPropertyIndex = findPropertyIndex(propertyID); + // Custom properties are never shorthands. + return ""; +} + +template<typename T> +String StylePropertySet::getPropertyValue(T property) const +{ + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(property); + if (value) + return value->cssText(); + return serializeShorthand(*this, property); +} +template CORE_EXPORT String StylePropertySet::getPropertyValue<CSSPropertyID>(CSSPropertyID) const; +template CORE_EXPORT String StylePropertySet::getPropertyValue<AtomicString>(AtomicString) const; + +template<typename T> +PassRefPtrWillBeRawPtr<CSSValue> StylePropertySet::getPropertyCSSValue(T property) const +{ + int foundPropertyIndex = findPropertyIndex(property); if (foundPropertyIndex == -1) return nullptr; return propertyAt(foundPropertyIndex).value(); } +template CORE_EXPORT PassRefPtrWillBeRawPtr<CSSValue> StylePropertySet::getPropertyCSSValue<CSSPropertyID>(CSSPropertyID) const; +template CORE_EXPORT PassRefPtrWillBeRawPtr<CSSValue> StylePropertySet::getPropertyCSSValue<AtomicString>(AtomicString) const; DEFINE_TRACE(StylePropertySet) { @@ -183,38 +226,53 @@ return removePropertiesInSet(shorthand.properties(), shorthand.length()); } -bool MutableStylePropertySet::removeProperty(CSSPropertyID propertyID, String* returnText) +bool MutableStylePropertySet::removePropertyAtIndex(int propertyIndex, String* returnText) { - if (removeShorthandProperty(propertyID)) { - // FIXME: Return an equivalent shorthand when possible. - if (returnText) - *returnText = ""; - return true; - } - - int foundPropertyIndex = findPropertyIndex(propertyID); - if (foundPropertyIndex == -1) { + if (propertyIndex == -1) { if (returnText) *returnText = ""; return false; } if (returnText) - *returnText = propertyAt(foundPropertyIndex).value()->cssText(); + *returnText = propertyAt(propertyIndex).value()->cssText(); // A more efficient removal strategy would involve marking entries as empty // and sweeping them when the vector grows too big. - m_propertyVector.remove(foundPropertyIndex); + m_propertyVector.remove(propertyIndex); return true; } -bool StylePropertySet::propertyIsImportant(CSSPropertyID propertyID) const +template<typename T> +bool MutableStylePropertySet::removeProperty(T property, String* returnText) { - int foundPropertyIndex = findPropertyIndex(propertyID); + if (removeShorthandProperty(property)) { + // FIXME: Return an equivalent shorthand when possible. + if (returnText) + *returnText = ""; + return true; + } + + int foundPropertyIndex = findPropertyIndex(property); + return removePropertyAtIndex(foundPropertyIndex, returnText); +} +template CORE_EXPORT bool MutableStylePropertySet::removeProperty(CSSPropertyID, String*); +template CORE_EXPORT bool MutableStylePropertySet::removeProperty(AtomicString, String*); + +template<typename T> +bool StylePropertySet::propertyIsImportant(T property) const +{ + int foundPropertyIndex = findPropertyIndex(property); if (foundPropertyIndex != -1) return propertyAt(foundPropertyIndex).isImportant(); + return shorthandIsImportant(property); +} +template bool StylePropertySet::propertyIsImportant<CSSPropertyID>(CSSPropertyID) const; +template bool StylePropertySet::propertyIsImportant<AtomicString>(AtomicString) const; +bool StylePropertySet::shorthandIsImportant(CSSPropertyID propertyID) const +{ StylePropertyShorthand shorthand = shorthandForProperty(propertyID); if (!shorthand.length()) return false; @@ -226,6 +284,12 @@ return true; } +bool StylePropertySet::shorthandIsImportant(AtomicString customPropertyName) const +{ + // Custom properties are never shorthands. + return false; +} + CSSPropertyID StylePropertySet::getPropertyShorthand(CSSPropertyID propertyID) const { int foundPropertyIndex = findPropertyIndex(propertyID); @@ -254,6 +318,13 @@ return CSSParser::parseValue(this, unresolvedProperty, value, important, contextStyleSheet); } +bool MutableStylePropertySet::setProperty(const AtomicString& customPropertyName, const String& value, bool important, StyleSheetContents* contextStyleSheet) +{ + if (value.isEmpty()) + return removeProperty(customPropertyName); + return CSSParser::parseValueForCustomProperty(this, customPropertyName, value, important, contextStyleSheet); +} + void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, PassRefPtrWillBeRawPtr<CSSValue> prpValue, bool important) { StylePropertyShorthand shorthand = shorthandForProperty(propertyID); @@ -330,6 +401,7 @@ unsigned size = other->propertyCount(); for (unsigned n = 0; n < size; ++n) { PropertyReference toMerge = other->propertyAt(n); + // TODO(leviw): This probably doesn't work correctly with Custom Properties CSSProperty* old = findCSSPropertyWithID(toMerge.id()); if (old) setProperty(toMerge.toCSSProperty(), old); @@ -386,6 +458,12 @@ CSSProperty* MutableStylePropertySet::findCSSPropertyWithID(CSSPropertyID propertyID) { + // TODO(leviw): Calling this with a custom property should probably assert, or this + // method should alternatively take a string used for custom properties and check it + // in that case. + if (propertyID == CSSPropertyVariable) + return nullptr; + int foundPropertyIndex = findPropertyIndex(propertyID); if (foundPropertyIndex == -1) return nullptr; @@ -458,27 +536,22 @@ return m_cssomWrapper.get(); } -int MutableStylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const +template<typename T> +int MutableStylePropertySet::findPropertyIndex(T property) const { const CSSProperty* begin = m_propertyVector.data(); const CSSProperty* end = begin + m_propertyVector.size(); - // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid - // the compiler converting it to an int multiple times in the loop. - uint16_t id = static_cast<uint16_t>(propertyID); - auto compare = [propertyID, id](const CSSProperty& property) -> bool { - if (property.metadata().m_propertyID == id) { - // Only enabled properties should be part of the style. - ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID)); - return true; - } - return false; - }; + uint16_t id = getConvertedCSSPropertyID(property); - const CSSProperty* it = std::find_if(begin, end, compare); + const CSSProperty* it = std::find_if(begin, end, [property, id](const CSSProperty& cssProperty) -> bool { + return isPropertyMatch(cssProperty.metadata(), *cssProperty.value(), id, property); + }); return (it == end) ? -1 : it - begin; } +template CORE_EXPORT int MutableStylePropertySet::findPropertyIndex(CSSPropertyID) const; +template CORE_EXPORT int MutableStylePropertySet::findPropertyIndex(AtomicString) const; DEFINE_TRACE_AFTER_DISPATCH(MutableStylePropertySet) {
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.h b/third_party/WebKit/Source/core/css/StylePropertySet.h index e88b4ee..de968399 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySet.h +++ b/third_party/WebKit/Source/core/css/StylePropertySet.h
@@ -90,13 +90,24 @@ unsigned propertyCount() const; bool isEmpty() const; PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); } - int findPropertyIndex(CSSPropertyID) const; + + template<typename T> // CSSPropertyID or AtomicString + int findPropertyIndex(T property) const; + bool hasProperty(CSSPropertyID property) const { return findPropertyIndex(property) != -1; } - PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; - String getPropertyValue(CSSPropertyID) const; + template<typename T> // CSSPropertyID or AtomicString + PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(T property) const; - bool propertyIsImportant(CSSPropertyID) const; + template<typename T> // CSSPropertyID or AtomicString + String getPropertyValue(T property) const; + + template<typename T> // CSSPropertyID or AtomicString + bool propertyIsImportant(T property) const; + + bool shorthandIsImportant(CSSPropertyID) const; + bool shorthandIsImportant(AtomicString customPropertyName) const; + CSSPropertyID getPropertyShorthand(CSSPropertyID) const; bool isPropertyImplicit(CSSPropertyID) const; @@ -156,7 +167,9 @@ const RawPtrWillBeMember<CSSValue>* valueArray() const; const StylePropertyMetadata* metadataArray() const; - int findPropertyIndex(CSSPropertyID) const; + + template<typename T> // CSSPropertyID or AtomicString + int findPropertyIndex(T property) const; DECLARE_TRACE_AFTER_DISPATCH(); @@ -197,13 +210,15 @@ // These expand shorthand properties into multiple properties. bool setProperty(CSSPropertyID unresolvedProperty, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); + bool setProperty(const AtomicString& customPropertyName, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); void setProperty(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important = false); // These do not. FIXME: This is too messy, we can do better. bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false); bool setProperty(const CSSProperty&, CSSProperty* slot = 0); - bool removeProperty(CSSPropertyID, String* returnText = 0); + template<typename T> // CSSPropertyID or AtomicString + bool removeProperty(T property, String* returnText = 0); bool removePropertiesInSet(const CSSPropertyID* set, unsigned length); void removeEquivalentProperties(const StylePropertySet*); void removeEquivalentProperties(const CSSStyleDeclaration*); @@ -214,7 +229,9 @@ void parseDeclarationList(const String& styleDeclaration, StyleSheetContents* contextStyleSheet); CSSStyleDeclaration* ensureCSSStyleDeclaration(); - int findPropertyIndex(CSSPropertyID) const; + + template<typename T> // CSSPropertyID or AtomicString + int findPropertyIndex(T property) const; DECLARE_TRACE_AFTER_DISPATCH(); @@ -223,7 +240,10 @@ explicit MutableStylePropertySet(const StylePropertySet&); MutableStylePropertySet(const CSSProperty* properties, unsigned count); + bool removePropertyAtIndex(int, String* returnText); + bool removeShorthandProperty(CSSPropertyID); + bool removeShorthandProperty(const AtomicString& customPropertyName) { return false; } CSSProperty* findCSSPropertyWithID(CSSPropertyID); OwnPtrWillBeMember<PropertySetCSSStyleDeclaration> m_cssomWrapper; @@ -288,11 +308,12 @@ } #endif // !ENABLE(OILPAN) -inline int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const +template<typename T> +inline int StylePropertySet::findPropertyIndex(T property) const { if (m_isMutable) - return toMutableStylePropertySet(this)->findPropertyIndex(propertyID); - return toImmutableStylePropertySet(this)->findPropertyIndex(propertyID); + return toMutableStylePropertySet(this)->findPropertyIndex(property); + return toImmutableStylePropertySet(this)->findPropertyIndex(property); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp index 4e84fa1a..fc5ce6a 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParser.cpp
@@ -17,6 +17,7 @@ #include "core/css/parser/CSSSelectorParser.h" #include "core/css/parser/CSSSupportsParser.h" #include "core/css/parser/CSSTokenizer.h" +#include "core/css/parser/CSSVariableParser.h" #include "core/layout/LayoutTheme.h" namespace blink { @@ -69,6 +70,20 @@ return parseValue(declaration, unresolvedProperty, string, important, context); } +bool CSSParser::parseValueForCustomProperty(MutableStylePropertySet* declaration, const AtomicString& propertyName, const String& value, bool important, StyleSheetContents* styleSheet) +{ + ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled() && CSSVariableParser::isValidVariableName(propertyName)); + if (value.isEmpty()) + return false; + CSSParserMode parserMode = declaration->cssParserMode(); + CSSParserContext context(parserMode, 0); + if (styleSheet) { + context = styleSheet->parserContext(); + context.setMode(parserMode); + } + return CSSParserImpl::parseVariableValue(declaration, propertyName, value, important, context); +} + bool CSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID unresolvedProperty, const String& string, bool important, const CSSParserContext& context) { return CSSParserImpl::parseValue(declaration, unresolvedProperty, string, important, context);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.h b/third_party/WebKit/Source/core/css/parser/CSSParser.h index 0c5bc6e..91769b63 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParser.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParser.h
@@ -35,6 +35,8 @@ // Returns whether anything was changed. static bool parseValue(MutableStylePropertySet*, CSSPropertyID unresolvedProperty, const String&, bool important, StyleSheetContents*); + static bool parseValueForCustomProperty(MutableStylePropertySet*, const AtomicString& propertyName, const String& value, bool important, StyleSheetContents*); + // This is for non-shorthands only static PassRefPtrWillBeRawPtr<CSSValue> parseSingleValue(CSSPropertyID, const String&, const CSSParserContext& = strictCSSParserContext());
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp index f84f25d4..f8bd98e 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
@@ -530,6 +530,8 @@ return valueID == CSSValueShow || valueID == CSSValueHide; case CSSPropertyFloat: // left | right | none return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone; + case CSSPropertyFontDisplay: // auto | block | swap | fallback | optional + return valueID == CSSValueAuto || valueID == CSSValueBlock || valueID == CSSValueSwap || valueID == CSSValueFallback || valueID == CSSValueOptional; case CSSPropertyFontStyle: // normal | italic | oblique return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique; case CSSPropertyFontStretch: // normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp index 58d56073..b1e5e81 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -51,6 +51,16 @@ return declaration->addParsedProperties(parser.m_parsedProperties); } +bool CSSParserImpl::parseVariableValue(MutableStylePropertySet* declaration, const AtomicString& propertyName, const String& value, bool important, const CSSParserContext& context) +{ + CSSParserImpl parser(context); + CSSTokenizer::Scope scope(value); + parser.consumeVariableValue(scope.tokenRange(), propertyName, important); + if (parser.m_parsedProperties.isEmpty()) + return false; + return declaration->addParsedProperties(parser.m_parsedProperties); +} + static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties) { // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found. @@ -698,7 +708,7 @@ } if (RuntimeEnabledFeatures::cssVariablesEnabled() && unresolvedProperty == CSSPropertyInvalid && CSSVariableParser::isValidVariableName(token)) { AtomicString variableName = token.value(); - consumeVariableDeclarationValue(range.makeSubRange(&range.peek(), declarationValueEnd), variableName, important); + consumeVariableValue(range.makeSubRange(&range.peek(), declarationValueEnd), variableName, important); return; } @@ -721,7 +731,7 @@ consumeDeclarationValue(range.makeSubRange(&range.peek(), declarationValueEnd), unresolvedProperty, important, ruleType); } -void CSSParserImpl::consumeVariableDeclarationValue(CSSParserTokenRange range, const AtomicString& variableName, bool important) +void CSSParserImpl::consumeVariableValue(CSSParserTokenRange range, const AtomicString& variableName, bool important) { if (RefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> value = CSSVariableParser::parseDeclarationValue(variableName, range)) m_parsedProperties.append(CSSProperty(CSSPropertyVariable, value.release(), important));
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h index a06caeeb..dadc1a1 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
@@ -55,6 +55,7 @@ }; static bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, const CSSParserContext&); + static bool parseVariableValue(MutableStylePropertySet*, const AtomicString& propertyName, const String&, bool important, const CSSParserContext&); static PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> parseInlineStyleDeclaration(const String&, Element*); static bool parseDeclarationList(MutableStylePropertySet*, const String&, const CSSParserContext&); static PassRefPtrWillBeRawPtr<StyleRuleBase> parseRule(const String&, const CSSParserContext&, StyleSheetContents*, AllowedRulesType); @@ -98,7 +99,7 @@ void consumeDeclarationList(CSSParserTokenRange, StyleRule::Type); void consumeDeclaration(CSSParserTokenRange, StyleRule::Type); void consumeDeclarationValue(CSSParserTokenRange, CSSPropertyID, bool important, StyleRule::Type); - void consumeVariableDeclarationValue(CSSParserTokenRange, const AtomicString& variableName, bool important); + void consumeVariableValue(CSSParserTokenRange, const AtomicString& propertyName, bool important); static PassOwnPtr<Vector<double>> consumeKeyframeKeyList(CSSParserTokenRange);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index b3b7bb3..7aba980 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -42,6 +42,7 @@ , m_currentShorthand(CSSPropertyInvalid) , m_implicitShorthand(false) { + m_range.consumeWhitespace(); } bool CSSPropertyParser::parseValue(CSSPropertyID unresolvedProperty, bool important, @@ -1874,7 +1875,6 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID unresolvedProperty) { CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty); - m_range.consumeWhitespace(); switch (property) { case CSSPropertyWillChange: return consumeWillChange(m_range); @@ -2134,8 +2134,6 @@ bool CSSPropertyParser::parseFontFaceDescriptor(CSSPropertyID propId) { RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; - - m_range.consumeWhitespace(); switch (propId) { case CSSPropertyFontFamily: if (consumeGenericFamily(m_range)) @@ -2148,6 +2146,7 @@ case CSSPropertyUnicodeRange: parsedValue = consumeFontFaceUnicodeRange(m_range); break; + case CSSPropertyFontDisplay: case CSSPropertyFontStretch: case CSSPropertyFontStyle: { CSSValueID id = m_range.consumeIncludingWhitespace().id(); @@ -2330,8 +2329,6 @@ { ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode())); - m_range.consumeWhitespace(); - switch (propId) { case CSSPropertyWidth: { RefPtrWillBeRawPtr<CSSValue> minWidth = consumeSingleViewportDescriptor(m_range, CSSPropertyMinWidth, m_context.mode()); @@ -2533,7 +2530,6 @@ { CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty); - m_range.consumeWhitespace(); CSSPropertyID oldShorthand = m_currentShorthand; // TODO(rob.buis): Remove this when the legacy property parser is gone m_currentShorthand = property;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSVariableParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.cpp index 94463b1..87738009 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSVariableParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.cpp
@@ -20,6 +20,11 @@ return value.length() >= 2 && value[0] == '-' && value[1] == '-'; } +bool CSSVariableParser::isValidVariableName(const String& string) +{ + return string.length() >= 2 && string[0] == '-' && string[1] == '-'; +} + bool isValidVariableReference(CSSParserTokenRange); bool classifyBlock(CSSParserTokenRange range, bool& hasReferences, bool isTopLevelBlock = true)
diff --git a/third_party/WebKit/Source/core/css/parser/CSSVariableParser.h b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.h index 7af43e1..6caadd0 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSVariableParser.h +++ b/third_party/WebKit/Source/core/css/parser/CSSVariableParser.h
@@ -21,6 +21,7 @@ static PassRefPtrWillBeRawPtr<CSSCustomPropertyDeclaration> parseDeclarationValue(const AtomicString&, CSSParserTokenRange); static bool isValidVariableName(const CSSParserToken&); + static bool isValidVariableName(const String&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/AttributeCollection.h b/third_party/WebKit/Source/core/dom/AttributeCollection.h index aa750bf..7e5d7aa 100644 --- a/third_party/WebKit/Source/core/dom/AttributeCollection.h +++ b/third_party/WebKit/Source/core/dom/AttributeCollection.h
@@ -33,7 +33,6 @@ #ifndef AttributeCollection_h #define AttributeCollection_h -#include "core/dom/Attr.h" #include "core/dom/Attribute.h" #include "wtf/Allocator.h" #include "wtf/Vector.h" @@ -68,7 +67,6 @@ iterator find(const AtomicString& name, bool shouldIgnoreCase) const; size_t findIndex(const QualifiedName&, bool shouldIgnoreCase = false) const; size_t findIndex(const AtomicString& name, bool shouldIgnoreCase) const; - size_t findIndex(Attr*) const; protected: size_t findSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const; @@ -184,19 +182,6 @@ } template <typename Container, typename ContainerMemberType> -size_t AttributeCollectionGeneric<Container, ContainerMemberType>::findIndex(Attr* attr) const -{ - // This relies on the fact that Attr's QualifiedName == the Attribute's name. - iterator end = this->end(); - unsigned index = 0; - for (iterator it = begin(); it != end; ++it, ++index) { - if (it->name() == attr->qualifiedName()) - return index; - } - return kNotFound; -} - -template <typename Container, typename ContainerMemberType> size_t AttributeCollectionGeneric<Container, ContainerMemberType>::findSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const { // Continue to checking case-insensitively and/or full namespaced names if necessary:
diff --git a/third_party/WebKit/Source/core/dom/DOMURL.h b/third_party/WebKit/Source/core/dom/DOMURL.h index 17dc127c45c..a5d11bd2 100644 --- a/third_party/WebKit/Source/core/dom/DOMURL.h +++ b/third_party/WebKit/Source/core/dom/DOMURL.h
@@ -52,11 +52,6 @@ { return new DOMURL(url, KURL(KURL(), base), exceptionState); } - static DOMURL* create(const String& url, DOMURL* base, ExceptionState& exceptionState) - { - ASSERT(base); - return new DOMURL(url, base->m_url, exceptionState); - } static String createObjectURL(ExecutionContext*, Blob*, ExceptionState&); static void revokeObjectURL(ExecutionContext*, const String&);
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 310aa41..8b824c9 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -1377,9 +1377,9 @@ void Document::didChangeVisibilityState() { - dispatchEvent(Event::create(EventTypeNames::visibilitychange)); + dispatchEvent(Event::createBubble(EventTypeNames::visibilitychange)); // Also send out the deprecated version until it can be removed. - dispatchEvent(Event::create(EventTypeNames::webkitvisibilitychange)); + dispatchEvent(Event::createBubble(EventTypeNames::webkitvisibilitychange)); PageVisibilityState state = pageVisibilityState(); for (DocumentVisibilityObserver* observer : m_visibilityObservers) @@ -1953,24 +1953,6 @@ } } -void Document::markFirstPaint() -{ - if (m_documentTiming.firstPaint() == 0) - m_documentTiming.markFirstPaint(); -} - -void Document::markFirstTextPaint() -{ - if (m_documentTiming.firstTextPaint() == 0) - m_documentTiming.markFirstTextPaint(); -} - -void Document::markFirstImagePaint() -{ - if (m_documentTiming.firstImagePaint() == 0) - m_documentTiming.markFirstImagePaint(); -} - void Document::setNeedsFocusedElementCheck() { setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::createWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus));
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index 926d796..56c7aa9 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -904,9 +904,6 @@ PassRefPtrWillBeRawPtr<TouchList> createTouchList(WillBeHeapVector<RefPtrWillBeMember<Touch>>&) const; const DocumentTiming& timing() const { return m_documentTiming; } - void markFirstPaint(); - void markFirstTextPaint(); - void markFirstImagePaint(); int requestAnimationFrame(FrameRequestCallback*); void cancelAnimationFrame(int id);
diff --git a/third_party/WebKit/Source/core/dom/DocumentTiming.cpp b/third_party/WebKit/Source/core/dom/DocumentTiming.cpp index 1b339f4..a047e59 100644 --- a/third_party/WebKit/Source/core/dom/DocumentTiming.cpp +++ b/third_party/WebKit/Source/core/dom/DocumentTiming.cpp
@@ -75,25 +75,4 @@ notifyDocumentTimingChanged(); } -void DocumentTiming::markFirstPaint() -{ - m_firstPaint = monotonicallyIncreasingTime(); - TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "firstPaint", m_firstPaint, "frame", frame()); - notifyDocumentTimingChanged(); -} - -void DocumentTiming::markFirstTextPaint() -{ - m_firstTextPaint = monotonicallyIncreasingTime(); - TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "firstTextPaint", m_firstTextPaint, "frame", frame()); - notifyDocumentTimingChanged(); -} - -void DocumentTiming::markFirstImagePaint() -{ - m_firstImagePaint = monotonicallyIncreasingTime(); - TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "firstImagePaint", m_firstImagePaint, "frame", frame()); - notifyDocumentTimingChanged(); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/DocumentTiming.h b/third_party/WebKit/Source/core/dom/DocumentTiming.h index 75a188e..158ad697 100644 --- a/third_party/WebKit/Source/core/dom/DocumentTiming.h +++ b/third_party/WebKit/Source/core/dom/DocumentTiming.h
@@ -44,9 +44,6 @@ void markDomContentLoadedEventEnd(); void markDomComplete(); void markFirstLayout(); - void markFirstPaint(); - void markFirstTextPaint(); - void markFirstImagePaint(); // These return monotonically-increasing seconds. double domLoading() const { return m_domLoading; } @@ -55,9 +52,6 @@ double domContentLoadedEventEnd() const { return m_domContentLoadedEventEnd; } double domComplete() const { return m_domComplete; } double firstLayout() const { return m_firstLayout; } - double firstPaint() const { return m_firstPaint; } - double firstTextPaint() const { return m_firstTextPaint; } - double firstImagePaint() const { return m_firstImagePaint; } DECLARE_TRACE(); @@ -71,9 +65,6 @@ double m_domContentLoadedEventEnd = 0.0; double m_domComplete = 0.0; double m_firstLayout = 0.0; - double m_firstPaint = 0.0; - double m_firstTextPaint = 0.0; - double m_firstImagePaint = 0.0; RawPtrWillBeMember<Document> m_document; };
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index cdd3038..e785c06 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -2201,7 +2201,7 @@ synchronizeAttribute(attr->qualifiedName()); - size_t index = elementData()->attributes().findIndex(attr); + size_t index = elementData()->attributes().findIndex(attr->qualifiedName()); if (index == kNotFound) { exceptionState.throwDOMException(NotFoundError, "The attribute was not found on this element."); return nullptr;
diff --git a/third_party/WebKit/Source/core/dom/URL.idl b/third_party/WebKit/Source/core/dom/URL.idl index 8bd9527..124d9ce 100644 --- a/third_party/WebKit/Source/core/dom/URL.idl +++ b/third_party/WebKit/Source/core/dom/URL.idl
@@ -27,11 +27,7 @@ // https://url.spec.whatwg.org/#url [ - // TODO(philipj): There should only be one constructor: - // Constructor(USVString url, optional USVString base) - Constructor(USVString url), - Constructor(USVString url, USVString base), - Constructor(USVString url, URL base), + Constructor(USVString url, optional USVString base), Exposed=(Window,Worker), ImplementedAs=DOMURL, RaisesException=Constructor,
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp index 6853498..8b403ce 100644 --- a/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp
@@ -58,12 +58,12 @@ // Mutate using the CSSOM wrapper so we get the same event behavior as a script. // Setting to null string removes the property. We don't have internal version of removeProperty. - m_element->style()->setPropertyInternal(m_property, String(), false, IGNORE_EXCEPTION); + m_element->style()->setPropertyInternal(m_property, String(), String(), false, IGNORE_EXCEPTION); } void RemoveCSSPropertyCommand::doUnapply() { - m_element->style()->setPropertyInternal(m_property, m_oldValue, m_important, IGNORE_EXCEPTION); + m_element->style()->setPropertyInternal(m_property, String(), m_oldValue, m_important, IGNORE_EXCEPTION); } DEFINE_TRACE(RemoveCSSPropertyCommand)
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp index eeb0752..1284b2d8 100644 --- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -570,9 +570,9 @@ // Mutate using the CSSOM wrapper so we get the same event behavior as a script. if (isEnclosingBlock(element)) - element->style()->setPropertyInternal(CSSPropertyDisplay, "inline", false, IGNORE_EXCEPTION); + element->style()->setPropertyInternal(CSSPropertyDisplay, String(), "inline", false, IGNORE_EXCEPTION); if (element->layoutObject() && element->layoutObject()->style()->isFloating()) - element->style()->setPropertyInternal(CSSPropertyFloat, "none", false, IGNORE_EXCEPTION); + element->style()->setPropertyInternal(CSSPropertyFloat, String(), "none", false, IGNORE_EXCEPTION); } } }
diff --git a/third_party/WebKit/Source/core/events/EventTarget.idl b/third_party/WebKit/Source/core/events/EventTarget.idl index 9798b128..602c41ad27 100644 --- a/third_party/WebKit/Source/core/events/EventTarget.idl +++ b/third_party/WebKit/Source/core/events/EventTarget.idl
@@ -25,10 +25,7 @@ WillBeGarbageCollected, Exposed=(Window,Worker) ] interface EventTarget { - // FIXME: first 2 args should be required, but throwing TypeError breaks - // legacy content. http://crbug.com/353484 - // FIXME: type should not be nullable. - [Custom] void addEventListener(optional DOMString? type = null, optional EventListener? listener = null, optional (EventListenerOptions or boolean) options); - [Custom] void removeEventListener(optional DOMString? type = null, optional EventListener? listener = null, optional (EventListenerOptions or boolean) options); + [Custom] void addEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options); + [Custom] void removeEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options); [ImplementedAs=dispatchEventForBindings, RaisesException] boolean dispatchEvent(Event event); };
diff --git a/third_party/WebKit/Source/core/fetch/FontResource.cpp b/third_party/WebKit/Source/core/fetch/FontResource.cpp index 53d9d05..68f88e0 100644 --- a/third_party/WebKit/Source/core/fetch/FontResource.cpp +++ b/third_party/WebKit/Source/core/fetch/FontResource.cpp
@@ -38,7 +38,10 @@ namespace blink { -static const double fontLoadWaitLimitSec = 3.0; +// Durations of font-display periods. +// https://tabatkins.github.io/specs/css-font-display/#font-display-desc +static const double fontLoadWaitShortLimitSec = 0.1; +static const double fontLoadWaitLongLimitSec = 3.0; enum FontPackageFormat { PackageFormatUnknown, @@ -77,9 +80,9 @@ FontResource::FontResource(const ResourceRequest& resourceRequest) : Resource(resourceRequest, Font) , m_state(Unloaded) - , m_exceedsFontLoadWaitLimit(false) , m_corsFailed(false) - , m_fontLoadWaitLimitTimer(this, &FontResource::fontLoadWaitLimitCallback) + , m_fontLoadShortLimitTimer(this, &FontResource::fontLoadShortLimitCallback) + , m_fontLoadLongLimitTimer(this, &FontResource::fontLoadLongLimitCallback) { } @@ -121,7 +124,8 @@ if (m_state != LoadInitiated) { m_state = LoadInitiated; Resource::load(dl, m_options); - m_fontLoadWaitLimitTimer.startOneShot(fontLoadWaitLimitSec, BLINK_FROM_HERE); + m_fontLoadShortLimitTimer.startOneShot(fontLoadWaitShortLimitSec, BLINK_FROM_HERE); + m_fontLoadLongLimitTimer.startOneShot(fontLoadWaitLongLimitSec, BLINK_FROM_HERE); ResourceClientWalker<FontResourceClient> walker(m_clients); while (FontResourceClient* client = walker.next()) @@ -156,14 +160,22 @@ return m_data->hasOneRef(); } -void FontResource::fontLoadWaitLimitCallback(Timer<FontResource>*) +void FontResource::fontLoadShortLimitCallback(Timer<FontResource>*) { if (!isLoading()) return; - m_exceedsFontLoadWaitLimit = true; ResourceClientWalker<FontResourceClient> walker(m_clients); while (FontResourceClient* client = walker.next()) - client->fontLoadWaitLimitExceeded(this); + client->fontLoadShortLimitExceeded(this); +} + +void FontResource::fontLoadLongLimitCallback(Timer<FontResource>*) +{ + if (!isLoading()) + return; + ResourceClientWalker<FontResourceClient> walker(m_clients); + while (FontResourceClient* client = walker.next()) + client->fontLoadLongLimitExceeded(this); } void FontResource::allClientsRemoved() @@ -174,7 +186,8 @@ void FontResource::checkNotify() { - m_fontLoadWaitLimitTimer.stop(); + m_fontLoadShortLimitTimer.stop(); + m_fontLoadLongLimitTimer.stop(); ResourceClientWalker<FontResourceClient> w(m_clients); while (FontResourceClient* c = w.next()) c->fontLoaded(this);
diff --git a/third_party/WebKit/Source/core/fetch/FontResource.h b/third_party/WebKit/Source/core/fetch/FontResource.h index 0483dec2..6e6db47b 100644 --- a/third_party/WebKit/Source/core/fetch/FontResource.h +++ b/third_party/WebKit/Source/core/fetch/FontResource.h
@@ -53,7 +53,6 @@ void allClientsRemoved() override; void beginLoadIfNeeded(ResourceFetcher* dl); bool stillNeedsLoad() const override { return m_state != LoadInitiated; } - bool exceedsFontLoadWaitLimit() const { return m_exceedsFontLoadWaitLimit; } bool loadScheduled() const { return m_state != Unloaded; } void didScheduleLoad(); @@ -83,16 +82,17 @@ FontResource(const ResourceRequest&); void checkNotify() override; - void fontLoadWaitLimitCallback(Timer<FontResource>*); + void fontLoadShortLimitCallback(Timer<FontResource>*); + void fontLoadLongLimitCallback(Timer<FontResource>*); enum State { Unloaded, LoadScheduled, LoadInitiated }; OwnPtr<FontCustomPlatformData> m_fontData; String m_otsParsingMessage; State m_state; - bool m_exceedsFontLoadWaitLimit; bool m_corsFailed; - Timer<FontResource> m_fontLoadWaitLimitTimer; + Timer<FontResource> m_fontLoadShortLimitTimer; + Timer<FontResource> m_fontLoadLongLimitTimer; friend class MemoryCache; }; @@ -106,7 +106,8 @@ ResourceClientType resourceClientType() const final { return expectedType(); } virtual void fontLoaded(FontResource*) {} virtual void didStartFontLoad(FontResource*) {} - virtual void fontLoadWaitLimitExceeded(FontResource*) {} + virtual void fontLoadShortLimitExceeded(FontResource*) {} + virtual void fontLoadLongLimitExceeded(FontResource*) {} }; }
diff --git a/third_party/WebKit/Source/core/frame/SubresourceIntegrity.cpp b/third_party/WebKit/Source/core/frame/SubresourceIntegrity.cpp index 216b614..a9c9739 100644 --- a/third_party/WebKit/Source/core/frame/SubresourceIntegrity.cpp +++ b/third_party/WebKit/Source/core/frame/SubresourceIntegrity.cpp
@@ -83,11 +83,11 @@ break; case HashAlgorithmSha384: weakerAlgorithms = weakerThanSha384; - length = ARRAY_SIZE(weakerThanSha384); + length = WTF_ARRAY_LENGTH(weakerThanSha384); break; case HashAlgorithmSha512: weakerAlgorithms = weakerThanSha512; - length = ARRAY_SIZE(weakerThanSha512); + length = WTF_ARRAY_LENGTH(weakerThanSha512); break; default: ASSERT_NOT_REACHED();
diff --git a/third_party/WebKit/Source/core/frame/SubresourceIntegrityTest.cpp b/third_party/WebKit/Source/core/frame/SubresourceIntegrityTest.cpp index cda218a..4e327b94 100644 --- a/third_party/WebKit/Source/core/frame/SubresourceIntegrityTest.cpp +++ b/third_party/WebKit/Source/core/frame/SubresourceIntegrityTest.cpp
@@ -316,7 +316,7 @@ expectParseMultipleHashes( "sha384-XVVXBGoYw6AJOh9J+Z8pBDMVVPfkBpngexkA7JqZu8d5GENND6TEIup/tA1v5GPr sha512-tbUPioKbVBplr0b1ucnWB57SJWt4x9dOE0Vy2mzCXvH3FepqDZ+07yMK81ytlg0MPaIrPAjcHqba5csorDWtKg==", kValidSha384AndSha512, - ARRAY_SIZE(kValidSha384AndSha512)); + WTF_ARRAY_LENGTH(kValidSha384AndSha512)); const IntegrityMetadata kValidSha256AndSha256[] = { {"BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=", HashAlgorithmSha256}, @@ -325,7 +325,7 @@ expectParseMultipleHashes( "sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE= sha256-deadbeef", kValidSha256AndSha256, - ARRAY_SIZE(kValidSha256AndSha256)); + WTF_ARRAY_LENGTH(kValidSha256AndSha256)); const IntegrityMetadata kValidSha256AndInvalidSha256[] = { {"BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=", HashAlgorithmSha256} @@ -333,7 +333,7 @@ expectParseMultipleHashes( "sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE= sha256-!!!!", kValidSha256AndInvalidSha256, - ARRAY_SIZE(kValidSha256AndInvalidSha256)); + WTF_ARRAY_LENGTH(kValidSha256AndInvalidSha256)); const IntegrityMetadata kInvalidSha256AndValidSha256[] = { {"BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=", HashAlgorithmSha256} @@ -341,7 +341,7 @@ expectParseMultipleHashes( "sha256-!!! sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=", kInvalidSha256AndValidSha256, - ARRAY_SIZE(kInvalidSha256AndValidSha256)); + WTF_ARRAY_LENGTH(kInvalidSha256AndValidSha256)); expectParse( "sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=?foo=bar",
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp index c7c7867..80baf8d3 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.cpp +++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -548,6 +548,7 @@ case CSSPropertyGridGap: return 513; case CSSPropertyFontFeatureSettings: return 514; case CSSPropertyVariable: return 515; + case CSSPropertyFontDisplay: return 516; // 1. Add new features above this line (don't change the assigned numbers of the existing // items). @@ -564,7 +565,7 @@ return 0; } -static int maximumCSSSampleId() { return 515; } +static int maximumCSSSampleId() { return 516; } void UseCounter::muteForInspector() { @@ -931,9 +932,6 @@ case PrefixedPerformanceResourceTimingBufferFull: return replacedBy("Performance.onwebkitresourcetimingbufferfull", "Performance.onresourcetimingbufferfull"); - case FetchAPIRequestContext: - return "Request.context is deprecated and will be removed in M46 (see: https://www.chromestatus.com/feature/5534702526005248)."; - case HeaderValueNotMatchingRFC7230: return "Header values not matching to RFC 7230, will be deprecated (see: https://www.chromestatus.com/feature/6457425448140800).";
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index 89a161a..9893db2 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -542,10 +542,6 @@ OfflineAudioContext = 653, PrefixedAudioContext = 654, PrefixedOfflineAudioContext = 655, - AddEventListenerNoArguments = 656, - AddEventListenerOneArgument = 657, - RemoveEventListenerNoArguments = 658, - RemoveEventListenerOneArgument = 659, MixedContentInNonHTTPSFrameThatRestrictsMixedContent = 661, MixedContentInSecureFrameThatDoesNotRestrictMixedContent = 662, MixedContentWebSocket = 663, @@ -779,7 +775,6 @@ CSSValuePrefixedMaxContent = 922, CSSValuePrefixedFitContent = 923, CSSValuePrefixedFillAvailable = 924, - FetchAPIRequestContext = 925, PresentationDefaultRequest = 926, PresentationAvailabilityChangeEventListener = 927, PresentationRequestConstructor = 928, @@ -890,6 +885,10 @@ ExecCommandOnInputOrTextarea = 1027, V8History_ScrollRestoration_AttributeGetter = 1028, V8History_ScrollRestoration_AttributeSetter = 1029, + SVG1DOMFilter = 1030, + OfflineAudioContextStartRendering = 1031, + OfflineAudioContextSuspend = 1032, + OfflineAudioContextResume = 1033, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/layout/BidiRunForLine.cpp b/third_party/WebKit/Source/core/layout/BidiRunForLine.cpp index 8ade9f8..4efe4182 100644 --- a/third_party/WebKit/Source/core/layout/BidiRunForLine.cpp +++ b/third_party/WebKit/Source/core/layout/BidiRunForLine.cpp
@@ -35,7 +35,7 @@ { LayoutObject* next = current; while (current) { - if (isIsolated(current->style()->unicodeBidi()) + if (treatAsIsolated(current->styleRef()) && (current->isLayoutInline() || current->isLayoutBlock())) { if (current != root) current = nullptr; @@ -56,7 +56,7 @@ break; if (!isIteratorTarget(LineLayoutItem(current)) - && !isIsolated(current->style()->unicodeBidi())) + && !treatAsIsolated(current->styleRef())) next = current->slowFirstChild(); if (!next) { @@ -114,17 +114,6 @@ } } -static void restoreIsolatedMidpointStates(InlineBidiResolver& topResolver, - InlineBidiResolver& isolatedResolver) -{ - while (!isolatedResolver.isolatedRuns().isEmpty()) { - BidiRun* run = isolatedResolver.isolatedRuns().last(); - isolatedResolver.isolatedRuns().removeLast(); - topResolver.setMidpointStateForIsolatedRun(run, - isolatedResolver.midpointStateForIsolatedRun(run)); - } -} - void constructBidiRunsForLine(InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly, @@ -137,28 +126,15 @@ const LayoutObject* currentRoot = topResolver.position().root(); topResolver.createBidiRunsForLine(endOfLine, override, previousLineBrokeCleanly); - struct BidiRunsWithRoot { - const LayoutObject* root; - Vector<BidiRun*> isolatedRuns; - }; - Vector<BidiRunsWithRoot> isolatedRunsStack; - while (true) { - if (topResolver.isolatedRuns().isEmpty()) { - if (isolatedRunsStack.isEmpty()) - break; - topResolver.isolatedRuns().appendVector(isolatedRunsStack.last().isolatedRuns); - ASSERT(!topResolver.isolatedRuns().isEmpty()); - currentRoot = isolatedRunsStack.last().root; - isolatedRunsStack.removeLast(); - } - + while (!topResolver.isolatedRuns().isEmpty()) { // It does not matter which order we resolve the runs as long as we // resolve them all. - BidiRun* isolatedRun = topResolver.isolatedRuns().last(); + BidiIsolatedRun isolatedRun = topResolver.isolatedRuns().last(); topResolver.isolatedRuns().removeLast(); + currentRoot = &isolatedRun.root; - LayoutObject* startObj = isolatedRun->object(); + LayoutObject* startObj = &isolatedRun.object; // Only inlines make sense with unicode-bidi: isolate (blocks are // already isolated). @@ -176,7 +152,7 @@ LineMidpointState& isolatedLineMidpointState = isolatedResolver.midpointState(); isolatedLineMidpointState = topResolver.midpointStateForIsolatedRun( - isolatedRun); + isolatedRun.runToReplace); EUnicodeBidi unicodeBidi = isolatedInline->style()->unicodeBidi(); TextDirection direction; if (unicodeBidi == Plaintext) { @@ -197,7 +173,7 @@ // createBidiRunsForLine. This can be but is not necessarily the first // run within the isolate. InlineIterator iter = InlineIterator(LineLayoutItem(isolatedInline), LineLayoutItem(startObj), - isolatedRun->m_start); + isolatedRun.position); isolatedResolver.setPositionIgnoringNestedIsolates(iter); // We stop at the next end of line; we may re-enter this isolate in the // next call to constructBidiRuns(). @@ -209,16 +185,16 @@ ASSERT(isolatedResolver.runs().runCount()); if (isolatedResolver.runs().runCount()) - bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs()); + bidiRuns.replaceRunWithRuns(&isolatedRun.runToReplace, isolatedResolver.runs()); // If we encountered any nested isolate runs, save them for later // processing. - if (!isolatedResolver.isolatedRuns().isEmpty()) { - isolatedRunsStack.resize(isolatedRunsStack.size() + 1); - isolatedRunsStack.last().isolatedRuns.appendVector( - isolatedResolver.isolatedRuns()); - isolatedRunsStack.last().root = isolatedInline; - restoreIsolatedMidpointStates(topResolver, isolatedResolver); + while (!isolatedResolver.isolatedRuns().isEmpty()) { + BidiIsolatedRun runWithContext = isolatedResolver.isolatedRuns().last(); + isolatedResolver.isolatedRuns().removeLast(); + topResolver.setMidpointStateForIsolatedRun(runWithContext.runToReplace, + isolatedResolver.midpointStateForIsolatedRun(runWithContext.runToReplace)); + topResolver.isolatedRuns().append(runWithContext); } } }
diff --git a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp index 3de1e264..55e3dd19 100644 --- a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp +++ b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
@@ -246,11 +246,9 @@ if (isFirstAfterBreak && !box.hasForcedBreakBefore()) { // This box is first after a soft break. LayoutUnit strut = box.paginationStrut(); - if (breakability == LayoutBox::ForbidBreaks) { - // Since we cannot break inside the box, just figure out how much more space we would - // need to prevent it from being pushed to the next column. - recordSpaceShortage(box.logicalHeight() - strut); - } else if (m_pendingStrut == LayoutUnit::min()) { + // Figure out how much more space we would need to prevent it from being pushed to the next column. + recordSpaceShortage(box.logicalHeight() - strut); + if (breakability != LayoutBox::ForbidBreaks && m_pendingStrut == LayoutUnit::min()) { // We now want to look for the first piece of unbreakable content (e.g. a line or a // block-displayed image) inside this block. That ought to be a good candidate for // minimum space shortage; a much better one than reporting space shortage for the
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp index db014c3..34c0b07 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -449,14 +449,8 @@ if (descendant.hasLayer()) { Vector<LayoutRect> layerOutlineRects; descendant.addOutlineRects(layerOutlineRects, LayoutPoint(), includeBlockOverflows); - for (size_t i = 0; i < layerOutlineRects.size(); ++i) { - FloatQuad quadInBox = toLayoutBoxModelObject(descendant).localToContainerQuad(FloatQuad(FloatRect(layerOutlineRects[i])), this); - LayoutRect rect = LayoutRect(quadInBox.boundingBox()); - if (!rect.isEmpty()) { - rect.moveBy(additionalOffset); - rects.append(rect); - } - } + descendant.localToContainerRects(layerOutlineRects, this, LayoutPoint(), additionalOffset); + rects.appendVector(layerOutlineRects); return; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index d3ba572..2a8d9614 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -2235,6 +2235,22 @@ return transformState.lastPlanarPoint(); } +void LayoutObject::localToContainerRects(Vector<LayoutRect>& rects, const LayoutBoxModelObject* paintInvalidationContainer, const LayoutPoint& preOffset, const LayoutPoint& postOffset) const +{ + for (size_t i = 0; i < rects.size(); ++i) { + LayoutRect& rect = rects[i]; + rect.moveBy(preOffset); + FloatQuad containerQuad = localToContainerQuad(FloatQuad(FloatRect(rect)), paintInvalidationContainer); + LayoutRect containerRect = LayoutRect(containerQuad.boundingBox()); + if (containerRect.isEmpty()) { + rects.remove(i--); + continue; + } + containerRect.moveBy(postOffset); + rects[i] = containerRect; + } +} + FloatPoint LayoutObject::localToInvalidationBackingPoint(const LayoutPoint& localPoint, PaintLayer** backingLayer) { const LayoutBoxModelObject& paintInvalidationContainer = containerForPaintInvalidationOnRootedTree();
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h index 62831da..b0cdb10 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -944,6 +944,7 @@ // Convert a local quad into the coordinate system of container, taking transforms into account. FloatQuad localToContainerQuad(const FloatQuad&, const LayoutBoxModelObject* paintInvalidationContainer, MapCoordinatesFlags = 0, bool* wasFixed = nullptr) const; FloatPoint localToContainerPoint(const FloatPoint&, const LayoutBoxModelObject* paintInvalidationContainer, MapCoordinatesFlags = 0, bool* wasFixed = nullptr, const PaintInvalidationState* = nullptr) const; + void localToContainerRects(Vector<LayoutRect>&, const LayoutBoxModelObject* paintInvalidationContainer, const LayoutPoint& preOffset, const LayoutPoint& postOffset) const; // Convert a local point into the coordinate system of backing coordinates. Also returns the backing layer if needed. FloatPoint localToInvalidationBackingPoint(const LayoutPoint&, PaintLayer** backingLayer = nullptr);
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectChildList.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectChildList.cpp index 5ff94c0..a7cf9cc 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObjectChildList.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObjectChildList.cpp
@@ -99,9 +99,9 @@ oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling()); if (firstChild() == oldChild) - setFirstChild(oldChild->nextSibling()); + m_firstChild = oldChild->nextSibling(); if (lastChild() == oldChild) - setLastChild(oldChild->previousSibling()); + m_lastChild = oldChild->previousSibling(); oldChild->setPreviousSibling(nullptr); oldChild->setNextSibling(nullptr); @@ -135,7 +135,7 @@ newChild->setParent(owner); if (firstChild() == beforeChild) - setFirstChild(newChild); + m_firstChild = newChild; if (beforeChild) { LayoutObject* previousSibling = beforeChild->previousSibling(); @@ -148,7 +148,7 @@ if (lastChild()) lastChild()->setNextSibling(newChild); newChild->setPreviousSibling(lastChild()); - setLastChild(newChild); + m_lastChild = newChild; } if (!owner->documentBeingDestroyed() && notifyLayoutObject) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectChildList.h b/third_party/WebKit/Source/core/layout/LayoutObjectChildList.h index a8fd0f5..349a2ec 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObjectChildList.h +++ b/third_party/WebKit/Source/core/layout/LayoutObjectChildList.h
@@ -45,11 +45,6 @@ LayoutObject* firstChild() const { return m_firstChild; } LayoutObject* lastChild() const { return m_lastChild; } - // FIXME: Temporary while LayoutBox still exists. Eventually this will just happen during insert/append/remove methods on the child list, and nobody - // will need to manipulate firstChild or lastChild directly. - void setFirstChild(LayoutObject* child) { m_firstChild = child; } - void setLastChild(LayoutObject* child) { m_lastChild = child; } - void destroyLeftoverChildren(); LayoutObject* removeChildNode(LayoutObject* owner, LayoutObject*, bool notifyLayoutObject = true);
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp index 023c3dd..75d5286 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -53,6 +53,7 @@ #include "core/paint/PaintInfo.h" #include "core/paint/PaintLayerPainter.h" #include "core/paint/PaintLayerStackingNodeIterator.h" +#include "core/paint/PaintTiming.h" #include "core/paint/ScrollableAreaPainter.h" #include "core/paint/TransformRecorder.h" #include "core/plugins/PluginView.h" @@ -2402,21 +2403,26 @@ void CompositedLayerMapping::notifyFirstPaint() { - // TODO(ksakamoto): This shouldn't be reported to Document. crbug.com/544811 - if (Node* node = layoutObject()->node()) - node->document().markFirstPaint(); + if (PaintTiming* timing = m_owningLayer.paintTiming()) { + if (timing->firstPaint() == 0) + timing->markFirstPaint(); + } } void CompositedLayerMapping::notifyFirstTextPaint() { - if (Node* node = layoutObject()->node()) - node->document().markFirstTextPaint(); + if (PaintTiming* timing = m_owningLayer.paintTiming()) { + if (timing->firstTextPaint() == 0) + timing->markFirstTextPaint(); + } } void CompositedLayerMapping::notifyFirstImagePaint() { - if (Node* node = layoutObject()->node()) - node->document().markFirstImagePaint(); + if (PaintTiming* timing = m_owningLayer.paintTiming()) { + if (timing->firstImagePaint() == 0) + timing->markFirstImagePaint(); + } } IntRect CompositedLayerMapping::pixelSnappedCompositedBounds() const
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp index ad6b112..932937e 100644 --- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
@@ -795,7 +795,7 @@ IntRect PaintLayerCompositor::computeInterestRect(const GraphicsLayer* graphicsLayer, const IntRect&) const { - return IntRect(IntPoint(), m_layoutView.layoutSize(IncludeScrollbars)); + return enclosingIntRect(FloatRect(FloatPoint(), graphicsLayer->size())); } void PaintLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& interestRect) const
diff --git a/third_party/WebKit/Source/core/layout/line/InlineIterator.h b/third_party/WebKit/Source/core/layout/line/InlineIterator.h index 07108aba..6b9e13f 100644 --- a/third_party/WebKit/Source/core/layout/line/InlineIterator.h +++ b/third_party/WebKit/Source/core/layout/line/InlineIterator.h
@@ -33,6 +33,22 @@ namespace blink { +struct BidiIsolatedRun { + BidiIsolatedRun(LayoutObject& object, unsigned position, LayoutObject& root, BidiRun& runToReplace) + : object(object) + , root(root) + , runToReplace(runToReplace) + , position(position) + { + } + + LayoutObject& object; + LayoutObject& root; + BidiRun& runToReplace; + unsigned position; +}; + + // This class is used to LayoutInline subtrees, stepping by character within the // text children. InlineIterator will use bidiNext to find the next LayoutText // optionally notifying a BidiResolver every time it steps into/out of a LayoutInline. @@ -130,6 +146,11 @@ return dir == RTL ? RightToLeftOverride : LeftToRightOverride; } +static inline bool treatAsIsolated(const ComputedStyle& style) +{ + return isIsolated(style.unicodeBidi()) && style.rtlOrdering() == LogicalOrder; +} + template <class Observer> static inline void notifyObserverEnteredObject(Observer* observer, LineLayoutItem object) { @@ -144,7 +165,7 @@ // Thus we ignore any possible dir= attribute on the span. return; } - if (isIsolated(unicodeBidi)) { + if (treatAsIsolated(style)) { // Make sure that explicit embeddings are committed before we enter the isolated content. observer->commitExplicitEmbedding(observer->runs()); observer->enterIsolate(); @@ -166,7 +187,7 @@ EUnicodeBidi unicodeBidi = object.style()->unicodeBidi(); if (unicodeBidi == UBNormal) return; // Nothing to do for unicode-bidi: normal - if (isIsolated(unicodeBidi)) { + if (treatAsIsolated(object.styleRef())) { observer->exitIsolate(); return; } @@ -380,7 +401,7 @@ static inline bool endOfLineHasIsolatedObjectAncestor(const InlineIterator& isolatedIterator, const InlineIterator& ancestorItertor) { - if (!isolatedIterator.object() || !isIsolated(isolatedIterator.object().style()->unicodeBidi())) + if (!isolatedIterator.object() || !treatAsIsolated(isolatedIterator.object().styleRef())) return false; LineLayoutItem innerIsolatedObject = isolatedIterator.object(); @@ -532,7 +553,7 @@ static inline bool isIsolatedInline(LineLayoutItem object) { ASSERT(object); - return object.isLayoutInline() && isIsolated(object.style()->unicodeBidi()); + return object.isLayoutInline() && treatAsIsolated(object.styleRef()); } static inline LineLayoutItem highestContainingIsolateWithinRoot(LineLayoutItem object, LineLayoutItem root) @@ -565,14 +586,14 @@ // FIXME: This belongs on InlineBidiResolver, except it's a template specialization // of BidiResolver which knows nothing about LayoutObjects. -static inline BidiRun* addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolver, LineLayoutItem obj, unsigned pos) +static inline BidiRun* addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolver, LineLayoutItem obj, unsigned pos, LineLayoutItem root) { ASSERT(obj); BidiRun* isolatedRun = new BidiRun(pos, pos, obj, resolver.context(), resolver.dir()); resolver.runs().addRun(isolatedRun); // FIXME: isolatedRuns() could be a hash of object->run and then we could cheaply // ASSERT here that we didn't create multiple objects for the same inline. - resolver.isolatedRuns().append(isolatedRun); + resolver.isolatedRuns().append(BidiIsolatedRun(*obj, pos, *root, *isolatedRun)); return isolatedRun; } @@ -616,7 +637,7 @@ void commitExplicitEmbedding(BidiRunList<BidiRun>&) { } BidiRunList<BidiRun>& runs() { return m_runs; } - void addFakeRunIfNecessary(LineLayoutItem obj, unsigned pos, unsigned end, InlineBidiResolver& resolver) + void addFakeRunIfNecessary(LineLayoutItem obj, unsigned pos, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver) { // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine. // We'll be called for every span inside the isolated span so we just ignore subsequent calls. @@ -624,8 +645,8 @@ if (LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj)) return; if (!m_haveAddedFakeRunForRootIsolate) { - BidiRun* run = addPlaceholderRunForIsolatedInline(resolver, obj, pos); - resolver.setMidpointStateForIsolatedRun(run, m_midpointStateForRootIsolate); + BidiRun* run = addPlaceholderRunForIsolatedInline(resolver, obj, pos, root); + resolver.setMidpointStateForIsolatedRun(*run, m_midpointStateForRootIsolate); m_haveAddedFakeRunForRootIsolate = true; } // obj and pos together denote a single position in the inline, from which the parsing of the isolate will start. @@ -640,7 +661,7 @@ BidiRunList<BidiRun>& m_runs; }; -static void inline appendRunObjectIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker) +static void inline appendRunObjectIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker) { // Trailing space code creates empty BidiRun objects, start == end, so // that case needs to be handled specifically. @@ -655,14 +676,14 @@ if (end - start > limit) limitedEnd = start + limit; if (behavior == AppendingFakeRun) - tracker.addFakeRunIfNecessary(obj, start, limitedEnd, resolver); + tracker.addFakeRunIfNecessary(obj, start, limitedEnd, root, resolver); else resolver.runs().addRun(createRun(start, limitedEnd, obj, resolver)); start = limitedEnd; } } -static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LineLayoutItem obj, unsigned start, unsigned end, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker) +static void adjustMidpointsAndAppendRunsForObjectIfNeeded(LineLayoutItem obj, unsigned start, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver, AppendRunBehavior behavior, IsolateTracker& tracker) { if (start > end || LayoutBlockFlow::shouldSkipCreatingRunsForObject(obj)) return; @@ -681,10 +702,10 @@ start = nextMidpoint.offset(); lineMidpointState.incrementCurrentMidpoint(); if (start < end) - return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, resolver, behavior, tracker); + return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, root, resolver, behavior, tracker); } else { if (!haveNextMidpoint || (obj != nextMidpoint.object())) { - appendRunObjectIfNecessary(obj, start, end, resolver, behavior, tracker); + appendRunObjectIfNecessary(obj, start, end, root, resolver, behavior, tracker); return; } @@ -695,19 +716,19 @@ lineMidpointState.incrementCurrentMidpoint(); if (nextMidpoint.offset() != UINT_MAX) { // UINT_MAX means stop at the object and don't nclude any of it. if (nextMidpoint.offset() + 1 > start) - appendRunObjectIfNecessary(obj, start, nextMidpoint.offset() + 1, resolver, behavior, tracker); - return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMidpoint.offset() + 1, end, resolver, behavior, tracker); + appendRunObjectIfNecessary(obj, start, nextMidpoint.offset() + 1, root, resolver, behavior, tracker); + return adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, nextMidpoint.offset() + 1, end, root, resolver, behavior, tracker); } } else { - appendRunObjectIfNecessary(obj, start, end, resolver, behavior, tracker); + appendRunObjectIfNecessary(obj, start, end, root, resolver, behavior, tracker); } } } -static inline void addFakeRunIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, InlineBidiResolver& resolver, IsolateTracker& tracker) +static inline void addFakeRunIfNecessary(LineLayoutItem obj, unsigned start, unsigned end, LineLayoutItem root, InlineBidiResolver& resolver, IsolateTracker& tracker) { tracker.setMidpointStateForRootIsolate(resolver.midpointState()); - adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), resolver, AppendingFakeRun, tracker); + adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), root, resolver, AppendingFakeRun, tracker); } template <> @@ -722,9 +743,9 @@ LineLayoutItem obj = m_sor.object(); while (obj && obj != m_eor.object() && obj != m_endOfRunAtEndOfLine.object()) { if (isolateTracker.inIsolate()) - addFakeRunIfNecessary(obj, start, obj.length(), *this, isolateTracker); + addFakeRunIfNecessary(obj, start, obj.length(), m_sor.root(), *this, isolateTracker); else - adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), *this, AppendingRunsForObject, isolateTracker); + adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, obj.length(), m_sor.root(), *this, AppendingRunsForObject, isolateTracker); // FIXME: start/obj should be an InlineIterator instead of two separate variables. start = 0; obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracker); @@ -739,9 +760,9 @@ // It's OK to add runs for zero-length LayoutObjects, just don't make the run larger than it should be int end = obj.length() ? pos + 1 : 0; if (isolateTracker.inIsolate()) - addFakeRunIfNecessary(obj, start, end, *this, isolateTracker); + addFakeRunIfNecessary(obj, start, end, m_sor.root(), *this, isolateTracker); else - adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, *this, AppendingRunsForObject, isolateTracker); + adjustMidpointsAndAppendRunsForObjectIfNeeded(obj, start, end, m_sor.root(), *this, AppendingRunsForObject, isolateTracker); } if (isEndOfLine)
diff --git a/third_party/WebKit/Source/core/layout/line/TrailingObjects.h b/third_party/WebKit/Source/core/layout/line/TrailingObjects.h index d59f8b6..8c0fa635 100644 --- a/third_party/WebKit/Source/core/layout/line/TrailingObjects.h +++ b/third_party/WebKit/Source/core/layout/line/TrailingObjects.h
@@ -34,10 +34,11 @@ class InlineIterator; struct BidiRun; +struct BidiIsolatedRun; -template <class Iterator, class Run> class BidiResolver; +template <class Iterator, class Run, class IsolatedRun> class BidiResolver; template <class Iterator> class MidpointState; -typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver; +typedef BidiResolver<InlineIterator, BidiRun, BidiIsolatedRun> InlineBidiResolver; typedef MidpointState<InlineIterator> LineMidpointState; // This class allows us to ensure lineboxes are created in the right place on the line when
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp index a025085..451740a 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
@@ -366,9 +366,8 @@ } else if (isSVGPolyElement(*svgElement)) { writeNameAndQuotedValue(ts, "points", toSVGPolyElement(*svgElement).points()->currentValue()->valueAsString()); } else if (isSVGPathElement(*svgElement)) { - String pathString; // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests. - buildStringFromByteStream(toSVGPathElement(*svgElement).pathByteStream(), pathString, NormalizedParsing); + String pathString = buildStringFromByteStream(toSVGPathElement(*svgElement).pathByteStream(), NormalizedParsing); writeNameAndQuotedValue(ts, "data", pathString); } else { ASSERT_NOT_REACHED();
diff --git a/third_party/WebKit/Source/core/paint/ObjectPainter.cpp b/third_party/WebKit/Source/core/paint/ObjectPainter.cpp index b8215705..987f680 100644 --- a/third_party/WebKit/Source/core/paint/ObjectPainter.cpp +++ b/third_party/WebKit/Source/core/paint/ObjectPainter.cpp
@@ -5,6 +5,7 @@ #include "config.h" #include "core/paint/ObjectPainter.h" +#include "core/layout/LayoutBlock.h" #include "core/layout/LayoutInline.h" #include "core/layout/LayoutObject.h" #include "core/layout/LayoutTheme.h" @@ -206,6 +207,14 @@ if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutObject, paintInfo.phase, paintOffset)) return; + // The result rects are in coordinates of m_layoutObject's border box. + // Block flipping is not applied yet if !m_layoutObject.isBox(). + if (!m_layoutObject.isBox() && m_layoutObject.styleRef().isFlippedBlocksWritingMode()) { + LayoutBlock* container = m_layoutObject.containingBlock(); + if (container) + m_layoutObject.localToContainerRects(outlineRects, container, -paintOffset, paintOffset); + } + Vector<IntRect> pixelSnappedOutlineRects; for (auto& r : outlineRects) pixelSnappedOutlineRects.append(pixelSnappedIntRect(r));
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp index 3b8af446..5410c7e 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -72,6 +72,7 @@ #include "core/page/Page.h" #include "core/page/scrolling/ScrollingCoordinator.h" #include "core/paint/FilterEffectBuilder.h" +#include "core/paint/PaintTiming.h" #include "platform/LengthFunctions.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" @@ -2750,6 +2751,13 @@ m_needsRepaint = false; } +PaintTiming* PaintLayer::paintTiming() +{ + if (Node* node = layoutObject()->node()) + return &PaintTiming::from(node->document()); + return nullptr; +} + DisableCompositingQueryAsserts::DisableCompositingQueryAsserts() : m_disabler(gCompositingQueryMode, CompositingQueriesAreAllowed) { }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h index b3c9248c..0516dd1a 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.h +++ b/third_party/WebKit/Source/core/paint/PaintLayer.h
@@ -61,14 +61,15 @@ namespace blink { +class CompositedLayerMapping; +class ComputedStyle; class FilterEffectBuilder; class FilterOperations; class HitTestRequest; class HitTestResult; class HitTestingTransformState; class PaintLayerCompositor; -class CompositedLayerMapping; -class ComputedStyle; +class PaintTiming; class TransformationMatrix; enum IncludeSelfOrNot { IncludeSelf, ExcludeSelf }; @@ -619,6 +620,8 @@ // For subsequence display items. DisplayItemClient displayItemClient() const { return toDisplayItemClient(this); } + PaintTiming* paintTiming(); + private: // Bounding box in the coordinates of this layer. LayoutRect logicalBoundingBox() const;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp index 282ec66..29ab883e 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -676,6 +676,9 @@ m_inOverflowRelayout = true; SubtreeLayoutScope layoutScope(box()); layoutScope.setNeedsLayout(&box(), LayoutInvalidationReason::ScrollbarChanged); + // TODO(wangxianzhu): Remove the following statement when paint invalidation + // can detect client box changes. crbug.com/560418. + box().setShouldDoFullPaintInvalidation(); if (box().isLayoutBlock()) { LayoutBlock& block = toLayoutBlock(box()); block.scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index e226295a..3969099 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -79,21 +79,26 @@ walk(*layoutView, localContext); } -static void deriveBorderBoxFromContainerContext(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) { + if (!object.isBoxModelObject()) + return; + + const LayoutBoxModelObject& boxModelObject = toLayoutBoxModelObject(object); + // TODO(trchen): There is some insanity going on with tables. Double check results. switch (object.styleRef().position()) { case StaticPosition: break; case RelativePosition: - context.paintOffset += object.offsetForInFlowPosition(); + context.paintOffset += boxModelObject.offsetForInFlowPosition(); break; case AbsolutePosition: context.currentTransform = context.transformForOutOfFlowPositioned; context.paintOffset = context.paintOffsetForOutOfFlowPositioned; break; case StickyPosition: - context.paintOffset += object.offsetForInFlowPosition(); + context.paintOffset += boxModelObject.offsetForInFlowPosition(); break; case FixedPosition: context.currentTransform = context.transformForFixedPositioned; @@ -102,14 +107,21 @@ default: ASSERT_NOT_REACHED(); } - if (object.isBox()) - context.paintOffset += toLayoutBox(object).locationOffset(); + if (boxModelObject.isBox()) + context.paintOffset += toLayoutBox(boxModelObject).locationOffset(); } -static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +static PassRefPtr<TransformPaintPropertyNode> createPaintOffsetTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) { - // TODO(trchen): Eliminate PaintLayer dependency. - bool shouldCreatePaintOffsetTranslationNode = object.layer() && object.layer()->paintsWithTransform(GlobalPaintNormalPhase); + bool shouldCreatePaintOffsetTranslationNode = false; + if (object.isSVGRoot()) { + // SVG doesn't use paint offset internally so emit a paint offset at the html->svg boundary. + shouldCreatePaintOffsetTranslationNode = true; + } else if (object.isBoxModelObject()) { + // TODO(trchen): Eliminate PaintLayer dependency. + PaintLayer* layer = toLayoutBoxModelObject(object).layer(); + shouldCreatePaintOffsetTranslationNode = layer && layer->paintsWithTransform(GlobalPaintNormalPhase); + } if (context.paintOffset == LayoutPoint() || !shouldCreatePaintOffsetTranslationNode) return nullptr; @@ -132,8 +144,20 @@ style.transformOriginZ()); } -static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +static PassRefPtr<TransformPaintPropertyNode> createTransformIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) { + if (object.isSVG() && !object.isSVGRoot()) { + const AffineTransform& transform = object.localToParentTransform(); + if (transform.isIdentity()) + return nullptr; + + // SVG's transform origin is baked into the localToParentTransform. + RefPtr<TransformPaintPropertyNode> newTransformNodeForTransform = TransformPaintPropertyNode::create( + transform, FloatPoint3D(0, 0, 0), context.currentTransform); + context.currentTransform = newTransformNodeForTransform.get(); + return newTransformNodeForTransform.release(); + } + const ComputedStyle& style = object.styleRef(); if (!object.isBox() || !style.hasTransform()) return nullptr; @@ -149,10 +173,10 @@ return newTransformNodeForTransform.release(); } -static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +static PassRefPtr<EffectPaintPropertyNode> createEffectIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) { const ComputedStyle& style = object.styleRef(); - if (!object.isBox() || !style.hasOpacity()) + if (!style.hasOpacity()) return nullptr; RefPtr<EffectPaintPropertyNode> newEffectNode = EffectPaintPropertyNode::create(style.opacity(), context.currentEffect); context.currentEffect = newEffectNode.get(); @@ -168,7 +192,7 @@ floatValueForLength(style.perspectiveOriginY(), borderBoxSize.height())); } -static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +static PassRefPtr<TransformPaintPropertyNode> createPerspectiveIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) { const ComputedStyle& style = object.styleRef(); if (!object.isBox() || !style.hasPerspective()) @@ -181,12 +205,12 @@ return newTransformNodeForPerspective.release(); } -static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +static PassRefPtr<TransformPaintPropertyNode> createScrollTranslationIfNeeded(const LayoutObject& object, PaintPropertyTreeBuilderContext& context) { - if (!object.hasOverflowClip()) + if (!object.isBoxModelObject() || !object.hasOverflowClip()) return nullptr; - PaintLayer* layer = object.layer(); + PaintLayer* layer = toLayoutBoxModelObject(object).layer(); ASSERT(layer); DoubleSize scrollOffset = layer->scrollableArea()->scrollOffset(); if (scrollOffset.isZero() && !layer->scrollsOverflow()) @@ -199,24 +223,26 @@ return newTransformNodeForScrollTranslation.release(); } -static void updateOutOfFlowContext(const LayoutBoxModelObject& object, PaintPropertyTreeBuilderContext& context) +static void updateOutOfFlowContext(const LayoutObject& object, bool createdNewTransform, PaintPropertyTreeBuilderContext& context) { - const ComputedStyle& style = object.styleRef(); - bool hasTransform = object.isBox() && style.hasTransform(); - if (style.position() != StaticPosition || hasTransform) { + // At the html->svg boundary (see: createPaintOffsetTranslationIfNeeded) the currentTransform is + // up-to-date for all children of the svg root element. Additionally, inside SVG, all positioning + // uses transforms. Therefore, we only need to check createdNewTransform and isSVGRoot() to + // ensure out-of-flow and fixed positioning is correct at the svg->html boundary. + + if (object.styleRef().position() != StaticPosition || createdNewTransform || object.isSVGRoot()) { context.transformForOutOfFlowPositioned = context.currentTransform; context.paintOffsetForOutOfFlowPositioned = context.paintOffset; } - if (hasTransform) { + + if (createdNewTransform || object.isSVGRoot()) { context.transformForFixedPositioned = context.currentTransform; context.paintOffsetForFixedPositioned = context.paintOffset; } } -void PaintPropertyTreeBuilder::walk(LayoutBoxModelObject& object, const PaintPropertyTreeBuilderContext& context) +void PaintPropertyTreeBuilder::walk(LayoutObject& object, const PaintPropertyTreeBuilderContext& context) { - ASSERT(object.isBox() != object.isLayoutInline()); // Either or. - PaintPropertyTreeBuilderContext localContext(context); deriveBorderBoxFromContainerContext(object, localContext); @@ -225,7 +251,7 @@ RefPtr<EffectPaintPropertyNode> newEffectNode = createEffectIfNeeded(object, localContext); RefPtr<TransformPaintPropertyNode> newTransformNodeForPerspective = createPerspectiveIfNeeded(object, localContext); RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = createScrollTranslationIfNeeded(object, localContext); - updateOutOfFlowContext(object, localContext); + updateOutOfFlowContext(object, newTransformNodeForTransform, localContext); if (newTransformNodeForPaintOffsetTranslation || newTransformNodeForTransform || newEffectNode || newTransformNodeForPerspective || newTransformNodeForScrollTranslation) { OwnPtr<ObjectPaintProperties> updatedPaintProperties = ObjectPaintProperties::create( @@ -241,15 +267,9 @@ // TODO(trchen): Walk subframes for LayoutFrame. - // TODO(trchen): Implement SVG walk. - if (object.isSVGRoot()) { - return; - } - for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) { - if (child->isText()) - continue; - walk(toLayoutBoxModelObject(*child), localContext); + if (child->isBoxModelObject() || child->isSVG()) + walk(*child, localContext); } }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h index eb7e4dd..d7861495 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
@@ -8,7 +8,7 @@ namespace blink { class FrameView; -class LayoutBoxModelObject; +class LayoutObject; struct PaintPropertyTreeBuilderContext; // This class walks the whole layout tree, beginning from the root FrameView, across @@ -23,7 +23,7 @@ private: void walk(FrameView&, const PaintPropertyTreeBuilderContext&); - void walk(LayoutBoxModelObject&, const PaintPropertyTreeBuilderContext&); + void walk(LayoutObject&, const PaintPropertyTreeBuilderContext&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index ada05d91..7f22a30 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -192,7 +192,7 @@ " <div id='grandChildWithoutOpacity'>" " <div id='greatGrandChildWithOpacity' style='opacity: 0.2'/>" " </div>" - " </div" + " </div>" "</div>"); LayoutObject& nodeWithoutOpacity = *document().getElementById("nodeWithoutOpacity")->layoutObject(); @@ -220,7 +220,7 @@ "<div id='nodeWithOpacity' style='opacity: 0.6'>" " <div id='childWithTransform' style='transform: translate3d(10px, 10px, 0px);'>" " <div id='grandChildWithOpacity' style='opacity: 0.4'/>" - " </div" + " </div>" "</div>"); LayoutObject& nodeWithOpacity = *document().getElementById("nodeWithOpacity")->layoutObject(); @@ -247,7 +247,7 @@ "<div id='nodeWithOpacity' style='opacity: 0.6'>" " <div id='childWithStackingContext' style='position:absolute;'>" " <div id='grandChildWithOpacity' style='opacity: 0.4'/>" - " </div" + " </div>" "</div>"); LayoutObject& nodeWithOpacity = *document().getElementById("nodeWithOpacity")->layoutObject(); @@ -266,4 +266,207 @@ EXPECT_EQ(nullptr, grandChildWithOpacityProperties->transform()); } +TEST_F(PaintPropertyTreeBuilderTest, EffectNodesInSVG) +{ + setBodyInnerHTML( + "<svg id='svgRoot'>" + " <g id='groupWithOpacity' opacity='0.6'>" + " <rect id='rectWithoutOpacity' />" + " <rect id='rectWithOpacity' opacity='0.4' />" + " <text id='textWithOpacity' opacity='0.2'>" + " <tspan id='tspanWithOpacity' opacity='0.1' />" + " </text>" + " </g>" + "</svg>"); + + LayoutObject& groupWithOpacity = *document().getElementById("groupWithOpacity")->layoutObject(); + ObjectPaintProperties* groupWithOpacityProperties = groupWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.6f, groupWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(nullptr, groupWithOpacityProperties->effect()->parent()); + + LayoutObject& rectWithoutOpacity = *document().getElementById("rectWithoutOpacity")->layoutObject(); + ObjectPaintProperties* rectWithoutOpacityProperties = rectWithoutOpacity.objectPaintProperties(); + EXPECT_EQ(nullptr, rectWithoutOpacityProperties); + + LayoutObject& rectWithOpacity = *document().getElementById("rectWithOpacity")->layoutObject(); + ObjectPaintProperties* rectWithOpacityProperties = rectWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.4f, rectWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(groupWithOpacityProperties->effect(), rectWithOpacityProperties->effect()->parent()); + + // Ensure that opacity nodes are created for LayoutSVGText which inherits from LayoutSVGBlock instead of LayoutSVGModelObject. + LayoutObject& textWithOpacity = *document().getElementById("textWithOpacity")->layoutObject(); + ObjectPaintProperties* textWithOpacityProperties = textWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.2f, textWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(groupWithOpacityProperties->effect(), textWithOpacityProperties->effect()->parent()); + + // Ensure that opacity nodes are created for LayoutSVGTSpan which inherits from LayoutSVGInline instead of LayoutSVGModelObject. + LayoutObject& tspanWithOpacity = *document().getElementById("tspanWithOpacity")->layoutObject(); + ObjectPaintProperties* tspanWithOpacityProperties = tspanWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.1f, tspanWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(textWithOpacityProperties->effect(), tspanWithOpacityProperties->effect()->parent()); +} + +TEST_F(PaintPropertyTreeBuilderTest, EffectNodesAcrossHTMLSVGBoundary) +{ + setBodyInnerHTML( + "<div id='divWithOpacity' style='opacity: 0.2;'>" + " <svg id='svgRootWithOpacity' style='opacity: 0.3;'>" + " <rect id='rectWithOpacity' opacity='0.4' />" + " </svg>" + "</div>"); + + LayoutObject& divWithOpacity = *document().getElementById("divWithOpacity")->layoutObject(); + ObjectPaintProperties* divWithOpacityProperties = divWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.2f, divWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(nullptr, divWithOpacityProperties->effect()->parent()); + + LayoutObject& svgRootWithOpacity = *document().getElementById("svgRootWithOpacity")->layoutObject(); + ObjectPaintProperties* svgRootWithOpacityProperties = svgRootWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.3f, svgRootWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(divWithOpacityProperties->effect(), svgRootWithOpacityProperties->effect()->parent()); + + LayoutObject& rectWithOpacity = *document().getElementById("rectWithOpacity")->layoutObject(); + ObjectPaintProperties* rectWithOpacityProperties = rectWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.4f, rectWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(svgRootWithOpacityProperties->effect(), rectWithOpacityProperties->effect()->parent()); +} + +TEST_F(PaintPropertyTreeBuilderTest, EffectNodesAcrossSVGHTMLBoundary) +{ + setBodyInnerHTML( + "<svg id='svgRootWithOpacity' style='opacity: 0.3;'>" + " <foreignObject id='foreignObjectWithOpacity' opacity='0.4'>" + " <body>" + " <span id='spanWithOpacity' style='opacity: 0.5'/>" + " </body>" + " </foreignObject>" + "</svg>"); + + LayoutObject& svgRootWithOpacity = *document().getElementById("svgRootWithOpacity")->layoutObject(); + ObjectPaintProperties* svgRootWithOpacityProperties = svgRootWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.3f, svgRootWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(nullptr, svgRootWithOpacityProperties->effect()->parent()); + + LayoutObject& foreignObjectWithOpacity = *document().getElementById("foreignObjectWithOpacity")->layoutObject(); + ObjectPaintProperties* foreignObjectWithOpacityProperties = foreignObjectWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.4f, foreignObjectWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(svgRootWithOpacityProperties->effect(), foreignObjectWithOpacityProperties->effect()->parent()); + + LayoutObject& spanWithOpacity = *document().getElementById("spanWithOpacity")->layoutObject(); + ObjectPaintProperties* spanWithOpacityProperties = spanWithOpacity.objectPaintProperties(); + EXPECT_EQ(0.5f, spanWithOpacityProperties->effect()->opacity()); + EXPECT_EQ(foreignObjectWithOpacityProperties->effect(), spanWithOpacityProperties->effect()->parent()); +} + +TEST_F(PaintPropertyTreeBuilderTest, TransformNodesInSVG) +{ + setBodyInnerHTML( + "<style>" + " body {" + " margin: 0px;" + " }" + " svg {" + " margin-left: 50px;" + " transform: translate3d(1px, 2px, 3px);" + " position: absolute;" + " left: 20px;" + " top: 25px;" + " }" + " rect {" + " transform: translate(100px, 100px) rotate(45deg);" + " transform-origin: 50px 25px;" + " }" + "</style>" + "<svg id='svgRootWith3dTransform' width='100px' height='100px'>" + " <rect id='rectWith2dTransform' width='100px' height='100px' />" + "</svg>"); + + LayoutObject& svgRootWith3dTransform = *document().getElementById("svgRootWith3dTransform")->layoutObject(); + ObjectPaintProperties* svgRootWith3dTransformProperties = svgRootWith3dTransform.objectPaintProperties(); + EXPECT_EQ(TransformationMatrix().translate3d(1, 2, 3), svgRootWith3dTransformProperties->transform()->matrix()); + EXPECT_EQ(FloatPoint3D(50, 50, 0), svgRootWith3dTransformProperties->transform()->origin()); + EXPECT_EQ(svgRootWith3dTransformProperties->paintOffsetTranslation(), svgRootWith3dTransformProperties->transform()->parent()); + EXPECT_EQ(TransformationMatrix().translate(70, 25), svgRootWith3dTransformProperties->paintOffsetTranslation()->matrix()); + EXPECT_EQ(document().view()->scrollTranslation(), svgRootWith3dTransformProperties->paintOffsetTranslation()->parent()); + + LayoutObject& rectWith2dTransform = *document().getElementById("rectWith2dTransform")->layoutObject(); + ObjectPaintProperties* rectWith2dTransformProperties = rectWith2dTransform.objectPaintProperties(); + TransformationMatrix matrix; + matrix.translate(100, 100); + matrix.rotate(45); + // SVG's transform origin is baked into the transform. + matrix.applyTransformOrigin(50, 25, 0); + EXPECT_EQ(matrix, rectWith2dTransformProperties->transform()->matrix()); + EXPECT_EQ(FloatPoint3D(0, 0, 0), rectWith2dTransformProperties->transform()->origin()); + // SVG does not use paint offset. + EXPECT_EQ(nullptr, rectWith2dTransformProperties->paintOffsetTranslation()); +} + +TEST_F(PaintPropertyTreeBuilderTest, SVGRootPaintOffsetTransformNode) +{ + setBodyInnerHTML( + "<style>body { margin: 0px; } </style>" + "<svg id='svg' style='margin-left: 50px; margin-top: 25px; width: 100px; height: 100px;' />"); + + LayoutObject& svg = *document().getElementById("svg")->layoutObject(); + ObjectPaintProperties* svgProperties = svg.objectPaintProperties(); + // Ensure that a paint offset transform is emitted for SVG, even without a CSS transform. + EXPECT_EQ(nullptr, svgProperties->transform()); + EXPECT_EQ(TransformationMatrix().translate(50, 25), svgProperties->paintOffsetTranslation()->matrix()); + EXPECT_EQ(document().view()->scrollTranslation(), svgProperties->paintOffsetTranslation()->parent()); +} + +TEST_F(PaintPropertyTreeBuilderTest, TransformNodesAcrossSVGHTMLBoundary) +{ + setBodyInnerHTML( + "<style> body { margin: 0px; } </style>" + "<svg id='svgWithTransform' style='transform: translate3d(1px, 2px, 3px);'>" + " <foreignObject>" + " <body>" + " <div id='divWithTransform' style='transform: translate3d(3px, 4px, 5px);'></div>" + " </body>" + " </foreignObject>" + "</svg>"); + + LayoutObject& svgWithTransform = *document().getElementById("svgWithTransform")->layoutObject(); + ObjectPaintProperties* svgWithTransformProperties = svgWithTransform.objectPaintProperties(); + EXPECT_EQ(TransformationMatrix().translate3d(1, 2, 3), svgWithTransformProperties->transform()->matrix()); + + LayoutObject& divWithTransform = *document().getElementById("divWithTransform")->layoutObject(); + ObjectPaintProperties* divWithTransformProperties = divWithTransform.objectPaintProperties(); + EXPECT_EQ(TransformationMatrix().translate3d(3, 4, 5), divWithTransformProperties->transform()->matrix()); + // Ensure the div's transform node is a child of the svg's transform node. + EXPECT_EQ(svgWithTransformProperties->transform(), divWithTransformProperties->transform()->parent()); +} + +TEST_F(PaintPropertyTreeBuilderTest, FixedTransformAncestorAcrossSVGHTMLBoundary) +{ + setBodyInnerHTML( + "<style> body { margin: 0px; } </style>" + "<svg id='svg' style='transform: translate3d(1px, 2px, 3px);'>" + " <g id='container' transform='translate(20 30)'>" + " <foreignObject>" + " <body>" + " <div id='fixed' style='position: fixed; left: 200px; top: 150px;'></div>" + " </body>" + " </foreignObject>" + " </g>" + "</svg>"); + + LayoutObject& svg = *document().getElementById("svg")->layoutObject(); + ObjectPaintProperties* svgProperties = svg.objectPaintProperties(); + EXPECT_EQ(TransformationMatrix().translate3d(1, 2, 3), svgProperties->transform()->matrix()); + + LayoutObject& container = *document().getElementById("container")->layoutObject(); + ObjectPaintProperties* containerProperties = container.objectPaintProperties(); + EXPECT_EQ(TransformationMatrix().translate(20, 30), containerProperties->transform()->matrix()); + EXPECT_EQ(svgProperties->transform(), containerProperties->transform()->parent()); + + Element* fixed = document().getElementById("fixed"); + ObjectPaintProperties* fixedProperties = fixed->layoutObject()->objectPaintProperties(); + EXPECT_EQ(TransformationMatrix().translate(200, 150), fixedProperties->paintOffsetTranslation()->matrix()); + // Ensure the fixed position element is rooted at the nearest transform container. + EXPECT_EQ(containerProperties->transform(), fixedProperties->paintOffsetTranslation()->parent()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.cpp b/third_party/WebKit/Source/core/paint/PaintTiming.cpp new file mode 100644 index 0000000..29b9507 --- /dev/null +++ b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
@@ -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 "config.h" +#include "core/paint/PaintTiming.h" + +#include "core/dom/Document.h" +#include "core/loader/DocumentLoader.h" +#include "platform/TraceEvent.h" +#include "wtf/RawPtr.h" + +namespace blink { + +static const char kSupplementName[] = "PaintTiming"; + +PaintTiming& PaintTiming::from(Document& document) +{ + PaintTiming* timing = static_cast<PaintTiming*>(WillBeHeapSupplement<Document>::from(document, kSupplementName)); + if (!timing) { + timing = new PaintTiming(document); + WillBeHeapSupplement<Document>::provideTo(document, kSupplementName, adoptPtrWillBeNoop(timing)); + } + return *timing; +} + +PaintTiming::PaintTiming(Document& document) + : m_document(document) +{ +} + +DEFINE_TRACE(PaintTiming) +{ + visitor->trace(m_document); +} + +LocalFrame* PaintTiming::frame() const +{ + return m_document ? m_document->frame() : nullptr; +} + +void PaintTiming::notifyPaintTimingChanged() +{ + if (m_document && m_document->loader()) + m_document->loader()->didChangePerformanceTiming(); +} + +void PaintTiming::markFirstPaint() +{ + m_firstPaint = monotonicallyIncreasingTime(); + TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "firstPaint", m_firstPaint, "frame", frame()); + notifyPaintTimingChanged(); +} + +void PaintTiming::markFirstTextPaint() +{ + m_firstTextPaint = monotonicallyIncreasingTime(); + TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "firstTextPaint", m_firstTextPaint, "frame", frame()); + notifyPaintTimingChanged(); +} + +void PaintTiming::markFirstImagePaint() +{ + m_firstImagePaint = monotonicallyIncreasingTime(); + TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "firstImagePaint", m_firstImagePaint, "frame", frame()); + notifyPaintTimingChanged(); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.h b/third_party/WebKit/Source/core/paint/PaintTiming.h new file mode 100644 index 0000000..6336609 --- /dev/null +++ b/third_party/WebKit/Source/core/paint/PaintTiming.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 PaintTiming_h +#define PaintTiming_h + +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" + +namespace blink { + +class Document; +class LocalFrame; + +class PaintTiming final : public NoBaseWillBeGarbageCollectedFinalized<PaintTiming>, public WillBeHeapSupplement<Document> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(PaintTiming); +public: + virtual ~PaintTiming() { } + + static PaintTiming& from(Document&); + + void markFirstPaint(); + void markFirstTextPaint(); + void markFirstImagePaint(); + + // These return monotonically-increasing seconds. + double firstPaint() const { return m_firstPaint; } + double firstTextPaint() const { return m_firstTextPaint; } + double firstImagePaint() const { return m_firstImagePaint; } + + DECLARE_VIRTUAL_TRACE(); + +private: + explicit PaintTiming(Document&); + LocalFrame* frame() const; + void notifyPaintTimingChanged(); + + double m_firstPaint = 0.0; + double m_firstTextPaint = 0.0; + double m_firstImagePaint = 0.0; + + RawPtrWillBeMember<Document> m_document; +}; + +} + +#endif
diff --git a/third_party/WebKit/Source/core/svg/SVGComponentTransferFunctionElement.idl b/third_party/WebKit/Source/core/svg/SVGComponentTransferFunctionElement.idl index d4a34b87..beda57a 100644 --- a/third_party/WebKit/Source/core/svg/SVGComponentTransferFunctionElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGComponentTransferFunctionElement.idl
@@ -29,18 +29,18 @@ DoNotCheckConstants ] interface SVGComponentTransferFunctionElement : SVGElement { // Component Transfer Types - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration type; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumberList tableValues; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber slope; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber intercept; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber amplitude; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber exponent; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber offset; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration type; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumberList tableValues; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber slope; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber intercept; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber amplitude; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber exponent; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber offset; };
diff --git a/third_party/WebKit/Source/core/svg/SVGFEBlendElement.idl b/third_party/WebKit/Source/core/svg/SVGFEBlendElement.idl index 9de8f38..757b51c 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEBlendElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEBlendElement.idl
@@ -30,16 +30,16 @@ ] interface SVGFEBlendElement : SVGElement { // Blend Mode Types - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FEBLEND_MODE_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FEBLEND_MODE_NORMAL = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FEBLEND_MODE_MULTIPLY = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FEBLEND_MODE_SCREEN = 3; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FEBLEND_MODE_DARKEN = 4; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FEBLEND_MODE_LIGHTEN = 5; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FEBLEND_MODE_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FEBLEND_MODE_NORMAL = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FEBLEND_MODE_MULTIPLY = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FEBLEND_MODE_SCREEN = 3; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FEBLEND_MODE_DARKEN = 4; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FEBLEND_MODE_LIGHTEN = 5; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration mode; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration mode; }; SVGFEBlendElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.idl b/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.idl index bb13640..1ca0f03 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.idl
@@ -29,15 +29,15 @@ DoNotCheckConstants, ] interface SVGFEColorMatrixElement : SVGElement { // Color Matrix Types - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOLORMATRIX_TYPE_MATRIX = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOLORMATRIX_TYPE_SATURATE = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOLORMATRIX_TYPE_HUEROTATE = 3; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOLORMATRIX_TYPE_MATRIX = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOLORMATRIX_TYPE_SATURATE = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOLORMATRIX_TYPE_HUEROTATE = 3; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration type; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumberList values; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration type; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumberList values; }; SVGFEColorMatrixElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.idl b/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.idl index 482571e..3c8ecd54 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEComponentTransferElement.idl
@@ -26,7 +26,7 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFEComponentTransferElement interface SVGFEComponentTransferElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; }; SVGFEComponentTransferElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFECompositeElement.idl b/third_party/WebKit/Source/core/svg/SVGFECompositeElement.idl index 66ba771..4c3546e 100644 --- a/third_party/WebKit/Source/core/svg/SVGFECompositeElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFECompositeElement.idl
@@ -29,21 +29,21 @@ DoNotCheckConstants, ] interface SVGFECompositeElement : SVGElement { // Composite Operators - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPOSITE_OPERATOR_OVER = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPOSITE_OPERATOR_IN = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPOSITE_OPERATOR_OUT = 3; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPOSITE_OPERATOR_ATOP = 4; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPOSITE_OPERATOR_XOR = 5; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_OVER = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_IN = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_OUT = 3; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_ATOP = 4; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_XOR = 5; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM,ImplementedAs=svgOperator] readonly attribute SVGAnimatedEnumeration operator; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber k1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber k2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber k3; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber k4; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM,ImplementedAs=svgOperator, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration operator; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber k1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber k2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber k3; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber k4; }; SVGFECompositeElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl index a1db16d..8b054ff9 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.idl
@@ -29,22 +29,22 @@ DoNotCheckConstants, ] interface SVGFEConvolveMatrixElement : SVGElement { // Edge Mode Values - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_EDGEMODE_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_EDGEMODE_DUPLICATE = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_EDGEMODE_WRAP = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_EDGEMODE_NONE = 3; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_EDGEMODE_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_EDGEMODE_DUPLICATE = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_EDGEMODE_WRAP = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_EDGEMODE_NONE = 3; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedInteger orderX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedInteger orderY; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumberList kernelMatrix; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber divisor; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber bias; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedInteger targetX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedInteger targetY; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration edgeMode; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber kernelUnitLengthX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber kernelUnitLengthY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedInteger orderX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedInteger orderY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumberList kernelMatrix; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber divisor; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber bias; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedInteger targetX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedInteger targetY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration edgeMode; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthY; // TODO(philipj): The following was part of SVG 1.1: // http://www.w3.org/TR/SVG11/filters.html#InterfaceSVGFEConvolveMatrixElement
diff --git a/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.idl b/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.idl index b9b35cfb..a8ebaf5 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.idl
@@ -26,11 +26,11 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFEDiffuseLightingElement interface SVGFEDiffuseLightingElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber surfaceScale; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber diffuseConstant; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber kernelUnitLengthX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber kernelUnitLengthY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber surfaceScale; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber diffuseConstant; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthY; }; SVGFEDiffuseLightingElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.idl b/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.idl index 43a50ae..204441b 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.idl
@@ -29,17 +29,17 @@ DoNotCheckConstants, ] interface SVGFEDisplacementMapElement : SVGElement { // Channel Selectors - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_CHANNEL_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_CHANNEL_R = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_CHANNEL_G = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_CHANNEL_B = 3; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_CHANNEL_A = 4; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_CHANNEL_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_CHANNEL_R = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_CHANNEL_G = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_CHANNEL_B = 3; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_CHANNEL_A = 4; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber scale; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration xChannelSelector; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration yChannelSelector; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber scale; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration xChannelSelector; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration yChannelSelector; }; SVGFEDisplacementMapElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEDistantLightElement.idl b/third_party/WebKit/Source/core/svg/SVGFEDistantLightElement.idl index 5ac50837..ad23a7a 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEDistantLightElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEDistantLightElement.idl
@@ -26,6 +26,6 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFEDistantLightElement interface SVGFEDistantLightElement : SVGElement { - readonly attribute SVGAnimatedNumber azimuth; - readonly attribute SVGAnimatedNumber elevation; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber azimuth; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber elevation; };
diff --git a/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.idl b/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.idl index ea44f41..d2df5b4e 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.idl
@@ -20,13 +20,13 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFEDropShadowElement interface SVGFEDropShadowElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber dx; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber dy; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber stdDeviationX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber stdDeviationY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dx; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dy; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber stdDeviationX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber stdDeviationY; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] void setStdDeviation(float stdDeviationX, float stdDeviationY); + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] void setStdDeviation(float stdDeviationX, float stdDeviationY); }; SVGFEDropShadowElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEGaussianBlurElement.idl b/third_party/WebKit/Source/core/svg/SVGFEGaussianBlurElement.idl index 238d344..cd16fd6d 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEGaussianBlurElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEGaussianBlurElement.idl
@@ -28,11 +28,11 @@ // Currently SVG 1.1 (SVG 2 members not implemented) interface SVGFEGaussianBlurElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber stdDeviationX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber stdDeviationY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber stdDeviationX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber stdDeviationY; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] void setStdDeviation(float stdDeviationX, float stdDeviationY); + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] void setStdDeviation(float stdDeviationX, float stdDeviationY); }; SVGFEGaussianBlurElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEImageElement.idl b/third_party/WebKit/Source/core/svg/SVGFEImageElement.idl index 2c4a272..a5c26b6 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEImageElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEImageElement.idl
@@ -28,7 +28,7 @@ // Currently SVG 1.1, SVG 2 members not implemented interface SVGFEImageElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio; }; SVGFEImageElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEMergeNodeElement.idl b/third_party/WebKit/Source/core/svg/SVGFEMergeNodeElement.idl index 9936f8d..bcee876da 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEMergeNodeElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEMergeNodeElement.idl
@@ -26,5 +26,5 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFEMergeNodeElement interface SVGFEMergeNodeElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; };
diff --git a/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.idl b/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.idl index eee1596..c150c33 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.idl
@@ -29,14 +29,14 @@ DoNotCheckConstants, ] interface SVGFEMorphologyElement : SVGElement { // Morphology Operators - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_MORPHOLOGY_OPERATOR_ERODE = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_MORPHOLOGY_OPERATOR_DILATE = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_MORPHOLOGY_OPERATOR_ERODE = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_MORPHOLOGY_OPERATOR_DILATE = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM,ImplementedAs=svgOperator] readonly attribute SVGAnimatedEnumeration operator; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber radiusX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber radiusY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM,ImplementedAs=svgOperator, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration operator; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber radiusX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber radiusY; }; SVGFEMorphologyElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEOffsetElement.idl b/third_party/WebKit/Source/core/svg/SVGFEOffsetElement.idl index bf73868..cc24267 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEOffsetElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEOffsetElement.idl
@@ -26,9 +26,9 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFEOffsetElement interface SVGFEOffsetElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber dx; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber dy; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dx; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber dy; }; SVGFEOffsetElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFEPointLightElement.idl b/third_party/WebKit/Source/core/svg/SVGFEPointLightElement.idl index fc732b7..60c2071 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEPointLightElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFEPointLightElement.idl
@@ -26,7 +26,7 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFEPointLightElement interface SVGFEPointLightElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber x; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber y; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber z; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber x; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber y; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber z; };
diff --git a/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.idl b/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.idl index 36ec8666..521e52c 100644 --- a/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.idl
@@ -26,12 +26,12 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFESpecularLightingElement interface SVGFESpecularLightingElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber surfaceScale; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber specularConstant; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber specularExponent; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber kernelUnitLengthX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber kernelUnitLengthY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber surfaceScale; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber specularConstant; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber specularExponent; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthY; }; SVGFESpecularLightingElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFESpotLightElement.idl b/third_party/WebKit/Source/core/svg/SVGFESpotLightElement.idl index 8ebca0ef..54cfb26 100644 --- a/third_party/WebKit/Source/core/svg/SVGFESpotLightElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFESpotLightElement.idl
@@ -26,12 +26,12 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFESpotLightElement interface SVGFESpotLightElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber x; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber y; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber z; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber pointsAtX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber pointsAtY; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber pointsAtZ; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber specularExponent; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber limitingConeAngle; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber x; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber y; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber z; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber pointsAtX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber pointsAtY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber pointsAtZ; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber specularExponent; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber limitingConeAngle; };
diff --git a/third_party/WebKit/Source/core/svg/SVGFETileElement.idl b/third_party/WebKit/Source/core/svg/SVGFETileElement.idl index b6cb6182..6654a3a 100644 --- a/third_party/WebKit/Source/core/svg/SVGFETileElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFETileElement.idl
@@ -26,7 +26,7 @@ // http://www.w3.org/TR/filter-effects/#InterfaceSVGFETileElement interface SVGFETileElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString in1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString in1; }; SVGFETileElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.idl b/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.idl index bb35e24..b54d528 100644 --- a/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.idl
@@ -29,21 +29,21 @@ DoNotCheckConstants, ] interface SVGFETurbulenceElement : SVGElement { // Turbulence Types - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE = 2; // Stitch Options - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_STITCHTYPE_UNKNOWN = 0; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_STITCHTYPE_STITCH = 1; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] const unsigned short SVG_STITCHTYPE_NOSTITCH = 2; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_STITCHTYPE_UNKNOWN = 0; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_STITCHTYPE_STITCH = 1; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] const unsigned short SVG_STITCHTYPE_NOSTITCH = 2; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber baseFrequencyX; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber baseFrequencyY; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedInteger numOctaves; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedNumber seed; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration stitchTiles; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration type; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber baseFrequencyX; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber baseFrequencyY; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedInteger numOctaves; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber seed; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration stitchTiles; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration type; }; SVGFETurbulenceElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterElement.idl b/third_party/WebKit/Source/core/svg/SVGFilterElement.idl index 3c990a7..09d9260 100644 --- a/third_party/WebKit/Source/core/svg/SVGFilterElement.idl +++ b/third_party/WebKit/Source/core/svg/SVGFilterElement.idl
@@ -29,12 +29,12 @@ [ TypeChecking=Interface, ] interface SVGFilterElement : SVGElement { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration filterUnits; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedEnumeration primitiveUnits; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength x; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength y; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength width; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength height; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration filterUnits; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration primitiveUnits; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength x; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength y; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength width; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength height; }; SVGFilterElement implements SVGURIReference;
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.idl b/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.idl index c12ffd5..9117c5efa 100644 --- a/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.idl +++ b/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.idl
@@ -29,9 +29,9 @@ [ NoInterfaceObject, // Always used on target of 'implements' ] interface SVGFilterPrimitiveStandardAttributes { - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength x; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength y; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength width; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedLength height; - [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOM] readonly attribute SVGAnimatedString result; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength x; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength y; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength width; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedLength height; + [RuntimeEnabled=SVG1DOM, MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedString result; };
diff --git a/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h b/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h index 51979d8..a84cf09 100644 --- a/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h +++ b/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.h
@@ -59,8 +59,8 @@ static AnimatedPropertyType classType() { return AnimatedIntegerOptionalInteger; } - PassRefPtrWillBeRawPtr<SVGInteger> firstInteger() { return m_firstInteger; } - PassRefPtrWillBeRawPtr<SVGInteger> secondInteger() { return m_secondInteger; } + PassRefPtrWillBeRawPtr<SVGInteger> firstInteger() const { return m_firstInteger; } + PassRefPtrWillBeRawPtr<SVGInteger> secondInteger() const { return m_secondInteger; } DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h b/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h index 0be4092b..956b5e1 100644 --- a/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h +++ b/third_party/WebKit/Source/core/svg/SVGNumberOptionalNumber.h
@@ -59,8 +59,8 @@ static AnimatedPropertyType classType() { return AnimatedNumberOptionalNumber; } - PassRefPtrWillBeRawPtr<SVGNumber> firstNumber() { return m_firstNumber; } - PassRefPtrWillBeRawPtr<SVGNumber> secondNumber() { return m_secondNumber; } + PassRefPtrWillBeRawPtr<SVGNumber> firstNumber() const { return m_firstNumber; } + PassRefPtrWillBeRawPtr<SVGNumber> secondNumber() const { return m_secondNumber; } DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/svg/SVGPath.cpp b/third_party/WebKit/Source/core/svg/SVGPath.cpp index 6fbd605f..fb9eebe 100644 --- a/third_party/WebKit/Source/core/svg/SVGPath.cpp +++ b/third_party/WebKit/Source/core/svg/SVGPath.cpp
@@ -122,14 +122,12 @@ String SVGPath::valueAsString() const { - String string; - buildStringFromByteStream(byteStream(), string, UnalteredParsing); - return string; + return buildStringFromByteStream(byteStream(), UnalteredParsing); } void SVGPath::setValueAsString(const String& string, ExceptionState& exceptionState) { - if (!buildSVGPathByteStreamFromString(string, ensureByteStream(), UnalteredParsing)) + if (!buildByteStreamFromString(string, ensureByteStream())) exceptionState.throwDOMException(SyntaxError, "Problem parsing path \"" + string + "\""); byteStreamChanged(); }
diff --git a/third_party/WebKit/Source/core/svg/SVGPathBuilder.h b/third_party/WebKit/Source/core/svg/SVGPathBuilder.h index 0ccecfd..5f3cea9f 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathBuilder.h +++ b/third_party/WebKit/Source/core/svg/SVGPathBuilder.h
@@ -35,9 +35,6 @@ SVGPathBuilder(Path& path) : m_path(path), m_closed(true) { } private: - void incrementPathSegmentCount() override { } - bool continueConsuming() override { return true; } - void emitSegment(const PathSegmentData&) override; Path& m_path;
diff --git a/third_party/WebKit/Source/core/svg/SVGPathByteStreamBuilder.h b/third_party/WebKit/Source/core/svg/SVGPathByteStreamBuilder.h index 94cb9373..9709497 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathByteStreamBuilder.h +++ b/third_party/WebKit/Source/core/svg/SVGPathByteStreamBuilder.h
@@ -31,9 +31,6 @@ SVGPathByteStreamBuilder(SVGPathByteStream&); private: - void incrementPathSegmentCount() override { } - bool continueConsuming() override { return true; } - void emitSegment(const PathSegmentData&) override; SVGPathByteStream& m_byteStream;
diff --git a/third_party/WebKit/Source/core/svg/SVGPathConsumer.h b/third_party/WebKit/Source/core/svg/SVGPathConsumer.h index 3d014bf..f8a4a9a 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathConsumer.h +++ b/third_party/WebKit/Source/core/svg/SVGPathConsumer.h
@@ -39,9 +39,6 @@ SVGPathConsumer() { } virtual ~SVGPathConsumer() { } - virtual void incrementPathSegmentCount() = 0; - virtual bool continueConsuming() = 0; - virtual void emitSegment(const PathSegmentData&) = 0; };
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp index 94b22165..676146da 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
@@ -24,7 +24,7 @@ #include "core/layout/svg/LayoutSVGPath.h" #include "core/svg/SVGDocumentExtensions.h" #include "core/svg/SVGMPathElement.h" -#include "core/svg/SVGPathUtilities.h" +#include "core/svg/SVGPathQuery.h" #include "core/svg/SVGPointTearOff.h" namespace blink { @@ -81,18 +81,18 @@ float SVGPathElement::getTotalLength() { - return getTotalLengthOfSVGPathByteStream(pathByteStream()); + return SVGPathQuery(pathByteStream()).getTotalLength(); } PassRefPtrWillBeRawPtr<SVGPointTearOff> SVGPathElement::getPointAtLength(float length) { - FloatPoint point = getPointAtLengthOfSVGPathByteStream(pathByteStream(), length); + FloatPoint point = SVGPathQuery(pathByteStream()).getPointAtLength(length); return SVGPointTearOff::create(SVGPoint::create(point), 0, PropertyIsNotAnimVal); } unsigned SVGPathElement::getPathSegAtLength(float length) { - return getSVGPathSegAtLengthFromSVGPathByteStream(pathByteStream(), length); + return SVGPathQuery(pathByteStream()).getPathSegIndexAtLength(length); } void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGPathParser.cpp b/third_party/WebKit/Source/core/svg/SVGPathParser.cpp index dda4d55..989ba01 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathParser.cpp +++ b/third_party/WebKit/Source/core/svg/SVGPathParser.cpp
@@ -50,38 +50,10 @@ return false; m_consumer->emitSegment(segment); - - if (!m_consumer->continueConsuming()) - return true; - - if (m_source->hasMoreData()) - m_consumer->incrementPathSegmentCount(); } return true; } -class NormalizingConsumer { - STACK_ALLOCATED(); -public: - NormalizingConsumer(SVGPathConsumer* consumer) - : m_consumer(consumer) - , m_lastCommand(PathSegUnknown) - { - ASSERT(m_consumer); - } - - void emitSegment(PathSegmentData&); - -private: - bool decomposeArcToCubic(const FloatPoint& currentPoint, const PathSegmentData&); - - SVGPathConsumer* m_consumer; - FloatPoint m_controlPoint; - FloatPoint m_currentPoint; - FloatPoint m_subPathPoint; - SVGPathSegType m_lastCommand; -}; - static FloatPoint reflectedPoint(const FloatPoint& reflectIn, const FloatPoint& pointToReflect) { return FloatPoint(2 * reflectIn.x() - pointToReflect.x(), 2 * reflectIn.y() - pointToReflect.y()); @@ -110,21 +82,21 @@ || command == PathSegCurveToQuadraticSmoothRel; } -void NormalizingConsumer::emitSegment(PathSegmentData& segment) +void SVGPathNormalizer::emitSegment(const PathSegmentData& segment) { - SVGPathSegType originalCommand = segment.command; + PathSegmentData normSeg = segment; // Convert relative points to absolute points. switch (segment.command) { case PathSegCurveToQuadraticRel: - segment.point1 += m_currentPoint; - segment.targetPoint += m_currentPoint; + normSeg.point1 += m_currentPoint; + normSeg.targetPoint += m_currentPoint; break; case PathSegCurveToCubicRel: - segment.point1 += m_currentPoint; + normSeg.point1 += m_currentPoint; /* fall through */ case PathSegCurveToCubicSmoothRel: - segment.point2 += m_currentPoint; + normSeg.point2 += m_currentPoint; /* fall through */ case PathSegMoveToRel: case PathSegLineToRel: @@ -132,17 +104,17 @@ case PathSegLineToVerticalRel: case PathSegCurveToQuadraticSmoothRel: case PathSegArcRel: - segment.targetPoint += m_currentPoint; + normSeg.targetPoint += m_currentPoint; break; case PathSegLineToHorizontalAbs: - segment.targetPoint.setY(m_currentPoint.y()); + normSeg.targetPoint.setY(m_currentPoint.y()); break; case PathSegLineToVerticalAbs: - segment.targetPoint.setX(m_currentPoint.x()); + normSeg.targetPoint.setX(m_currentPoint.x()); break; case PathSegClosePath: // Reset m_currentPoint for the next path. - segment.targetPoint = m_subPathPoint; + normSeg.targetPoint = m_subPathPoint; break; default: break; @@ -153,8 +125,8 @@ switch (segment.command) { case PathSegMoveToRel: case PathSegMoveToAbs: - m_subPathPoint = segment.targetPoint; - segment.command = PathSegMoveToAbs; + m_subPathPoint = normSeg.targetPoint; + normSeg.command = PathSegMoveToAbs; break; case PathSegLineToRel: case PathSegLineToAbs: @@ -162,68 +134,69 @@ case PathSegLineToHorizontalAbs: case PathSegLineToVerticalRel: case PathSegLineToVerticalAbs: - segment.command = PathSegLineToAbs; + normSeg.command = PathSegLineToAbs; break; case PathSegClosePath: + normSeg.command = PathSegClosePath; break; case PathSegCurveToCubicSmoothRel: case PathSegCurveToCubicSmoothAbs: if (!isCubicCommand(m_lastCommand)) - segment.point1 = m_currentPoint; + normSeg.point1 = m_currentPoint; else - segment.point1 = reflectedPoint(m_currentPoint, m_controlPoint); + normSeg.point1 = reflectedPoint(m_currentPoint, m_controlPoint); /* fall through */ case PathSegCurveToCubicRel: case PathSegCurveToCubicAbs: - m_controlPoint = segment.point2; - segment.command = PathSegCurveToCubicAbs; + m_controlPoint = normSeg.point2; + normSeg.command = PathSegCurveToCubicAbs; break; case PathSegCurveToQuadraticSmoothRel: case PathSegCurveToQuadraticSmoothAbs: if (!isQuadraticCommand(m_lastCommand)) - segment.point1 = m_currentPoint; + normSeg.point1 = m_currentPoint; else - segment.point1 = reflectedPoint(m_currentPoint, m_controlPoint); + normSeg.point1 = reflectedPoint(m_currentPoint, m_controlPoint); /* fall through */ case PathSegCurveToQuadraticRel: case PathSegCurveToQuadraticAbs: // Save the unmodified control point. - m_controlPoint = segment.point1; - segment.point1 = blendPoints(m_currentPoint, m_controlPoint); - segment.point2 = blendPoints(segment.targetPoint, m_controlPoint); - segment.command = PathSegCurveToCubicAbs; + m_controlPoint = normSeg.point1; + normSeg.point1 = blendPoints(m_currentPoint, m_controlPoint); + normSeg.point2 = blendPoints(normSeg.targetPoint, m_controlPoint); + normSeg.command = PathSegCurveToCubicAbs; break; case PathSegArcRel: case PathSegArcAbs: - if (!decomposeArcToCubic(m_currentPoint, segment)) { + if (!decomposeArcToCubic(m_currentPoint, normSeg)) { // On failure, emit a line segment to the target point. - segment.command = PathSegLineToAbs; + normSeg.command = PathSegLineToAbs; } else { // decomposeArcToCubic() has already emitted the normalized // segments, so set command to PathSegArcAbs, to skip any further // emit. - segment.command = PathSegArcAbs; + normSeg.command = PathSegArcAbs; } break; default: ASSERT_NOT_REACHED(); } - if (segment.command != PathSegArcAbs) - m_consumer->emitSegment(segment); + if (normSeg.command != PathSegArcAbs) + m_consumer->emitSegment(normSeg); - m_currentPoint = segment.targetPoint; + m_currentPoint = normSeg.targetPoint; - if (!isCubicCommand(originalCommand) && !isQuadraticCommand(originalCommand)) + if (!isCubicCommand(segment.command) && !isQuadraticCommand(segment.command)) m_controlPoint = m_currentPoint; - m_lastCommand = originalCommand; + m_lastCommand = segment.command; } // This works by converting the SVG arc to "simple" beziers. // Partly adapted from Niko's code in kdelibs/kdecore/svgicons. // See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter -bool NormalizingConsumer::decomposeArcToCubic(const FloatPoint& currentPoint, const PathSegmentData& arcSegment) +bool SVGPathNormalizer::decomposeArcToCubic(const FloatPoint& currentPoint, const PathSegmentData& arcSegment) { // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto") joining the endpoints. // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters @@ -327,7 +300,7 @@ bool SVGPathParser::parseAndNormalizePath() { - NormalizingConsumer normalizer(m_consumer); + SVGPathNormalizer normalizer(m_consumer); while (m_source->hasMoreData()) { PathSegmentData segment = m_source->parseSegment(); @@ -335,12 +308,6 @@ return false; normalizer.emitSegment(segment); - - if (!m_consumer->continueConsuming()) - return true; - - if (m_source->hasMoreData()) - m_consumer->incrementPathSegmentCount(); } return true; }
diff --git a/third_party/WebKit/Source/core/svg/SVGPathParser.h b/third_party/WebKit/Source/core/svg/SVGPathParser.h index 61c9e0ca..f5f78d2 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathParser.h +++ b/third_party/WebKit/Source/core/svg/SVGPathParser.h
@@ -70,6 +70,28 @@ SVGPathConsumer* m_consumer; }; +class SVGPathNormalizer { + STACK_ALLOCATED(); +public: + SVGPathNormalizer(SVGPathConsumer* consumer) + : m_consumer(consumer) + , m_lastCommand(PathSegUnknown) + { + ASSERT(m_consumer); + } + + void emitSegment(const PathSegmentData&); + +private: + bool decomposeArcToCubic(const FloatPoint& currentPoint, const PathSegmentData&); + + SVGPathConsumer* m_consumer; + FloatPoint m_controlPoint; + FloatPoint m_currentPoint; + FloatPoint m_subPathPoint; + SVGPathSegType m_lastCommand; +}; + } // namespace blink #endif // SVGPathParser_h
diff --git a/third_party/WebKit/Source/core/svg/SVGPathQuery.cpp b/third_party/WebKit/Source/core/svg/SVGPathQuery.cpp new file mode 100644 index 0000000..f7a596a5 --- /dev/null +++ b/third_party/WebKit/Source/core/svg/SVGPathQuery.cpp
@@ -0,0 +1,132 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "core/svg/SVGPathQuery.h" + +#include "core/svg/SVGPathByteStreamSource.h" +#include "core/svg/SVGPathConsumer.h" +#include "core/svg/SVGPathData.h" +#include "core/svg/SVGPathParser.h" +#include "platform/graphics/PathTraversalState.h" + +namespace blink { + +namespace { + +class SVGPathTraversalState final : public SVGPathConsumer { +public: + SVGPathTraversalState(PathTraversalState::PathTraversalAction traversalAction, float desiredLength = 0) + : m_traversalState(traversalAction) + , m_segmentIndex(0) + { + m_traversalState.m_desiredLength = desiredLength; + } + + unsigned segmentIndex() const { return m_segmentIndex; } + float totalLength() const { return m_traversalState.m_totalLength; } + FloatPoint computedPoint() const { return m_traversalState.m_current; } + + bool processSegment(bool hasMoreData) + { + m_traversalState.processSegment(); + if (m_traversalState.m_success) + return true; + if (hasMoreData) + m_segmentIndex++; + return false; + } + +private: + void emitSegment(const PathSegmentData&) override; + + PathTraversalState m_traversalState; + unsigned m_segmentIndex; +}; + +void SVGPathTraversalState::emitSegment(const PathSegmentData& segment) +{ + switch (segment.command) { + case PathSegMoveToAbs: + m_traversalState.m_totalLength += m_traversalState.moveTo(segment.targetPoint); + break; + case PathSegLineToAbs: + m_traversalState.m_totalLength += m_traversalState.lineTo(segment.targetPoint); + break; + case PathSegClosePath: + m_traversalState.m_totalLength += m_traversalState.closeSubpath(); + break; + case PathSegCurveToCubicAbs: + m_traversalState.m_totalLength += m_traversalState.cubicBezierTo(segment.point1, segment.point2, segment.targetPoint); + break; + default: + ASSERT_NOT_REACHED(); + } +} + +void executeQuery(const SVGPathByteStream& pathByteStream, SVGPathTraversalState& traversalState) +{ + SVGPathByteStreamSource source(pathByteStream); + SVGPathNormalizer normalizer(&traversalState); + + bool hasMoreData = source.hasMoreData(); + while (hasMoreData) { + PathSegmentData segment = source.parseSegment(); + ASSERT(segment.command != PathSegUnknown); + + normalizer.emitSegment(segment); + + hasMoreData = source.hasMoreData(); + if (traversalState.processSegment(hasMoreData)) + break; + } +} + +} + +SVGPathQuery::SVGPathQuery(const SVGPathByteStream& pathByteStream) + : m_pathByteStream(pathByteStream) +{ +} + +unsigned SVGPathQuery::getPathSegIndexAtLength(float length) const +{ + SVGPathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength, length); + executeQuery(m_pathByteStream, traversalState); + return traversalState.segmentIndex(); +} + +float SVGPathQuery::getTotalLength() const +{ + SVGPathTraversalState traversalState(PathTraversalState::TraversalTotalLength); + executeQuery(m_pathByteStream, traversalState); + return traversalState.totalLength(); +} + +FloatPoint SVGPathQuery::getPointAtLength(float length) const +{ + SVGPathTraversalState traversalState(PathTraversalState::TraversalPointAtLength, length); + executeQuery(m_pathByteStream, traversalState); + return traversalState.computedPoint(); +} + +}
diff --git a/third_party/WebKit/Source/core/svg/SVGPathQuery.h b/third_party/WebKit/Source/core/svg/SVGPathQuery.h new file mode 100644 index 0000000..93295f1 --- /dev/null +++ b/third_party/WebKit/Source/core/svg/SVGPathQuery.h
@@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SVGPathQuery_h +#define SVGPathQuery_h + +namespace blink { + +class FloatPoint; +class SVGPathByteStream; + +class SVGPathQuery { +public: + explicit SVGPathQuery(const SVGPathByteStream&); + + float getTotalLength() const; + FloatPoint getPointAtLength(float length) const; + unsigned getPathSegIndexAtLength(float length) const; + +private: + const SVGPathByteStream& m_pathByteStream; +}; + +} // namespace blink + +#endif // SVGPathQuery_h
diff --git a/third_party/WebKit/Source/core/svg/SVGPathStringBuilder.h b/third_party/WebKit/Source/core/svg/SVGPathStringBuilder.h index 7dd5e8f0..ebed2413 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathStringBuilder.h +++ b/third_party/WebKit/Source/core/svg/SVGPathStringBuilder.h
@@ -31,9 +31,6 @@ String result(); private: - void incrementPathSegmentCount() override { } - bool continueConsuming() override { return true; } - void emitSegment(const PathSegmentData&) override; StringBuilder m_stringBuilder;
diff --git a/third_party/WebKit/Source/core/svg/SVGPathTraversalStateBuilder.cpp b/third_party/WebKit/Source/core/svg/SVGPathTraversalStateBuilder.cpp deleted file mode 100644 index 50862f0..0000000 --- a/third_party/WebKit/Source/core/svg/SVGPathTraversalStateBuilder.cpp +++ /dev/null
@@ -1,79 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * Copyright (C) Research In Motion Limited 2010. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "core/svg/SVGPathTraversalStateBuilder.h" - -#include "core/svg/SVGPathData.h" -#include "platform/graphics/PathTraversalState.h" - -namespace blink { - -SVGPathTraversalStateBuilder::SVGPathTraversalStateBuilder(PathTraversalState::PathTraversalAction traversalAction, float desiredLength) - : m_traversalState(traversalAction) - , m_segmentIndex(0) -{ - m_traversalState.m_desiredLength = desiredLength; -} - -void SVGPathTraversalStateBuilder::emitSegment(const PathSegmentData& segment) -{ - switch (segment.command) { - case PathSegMoveToAbs: - m_traversalState.m_totalLength += m_traversalState.moveTo(segment.targetPoint); - break; - case PathSegLineToAbs: - m_traversalState.m_totalLength += m_traversalState.lineTo(segment.targetPoint); - break; - case PathSegClosePath: - m_traversalState.m_totalLength += m_traversalState.closeSubpath(); - break; - case PathSegCurveToCubicAbs: - m_traversalState.m_totalLength += m_traversalState.cubicBezierTo(segment.point1, segment.point2, segment.targetPoint); - break; - default: - ASSERT_NOT_REACHED(); - } -} - -bool SVGPathTraversalStateBuilder::continueConsuming() -{ - m_traversalState.processSegment(); - return !m_traversalState.m_success; -} - -void SVGPathTraversalStateBuilder::incrementPathSegmentCount() -{ - ++m_segmentIndex; -} - -float SVGPathTraversalStateBuilder::totalLength() -{ - return m_traversalState.m_totalLength; -} - -FloatPoint SVGPathTraversalStateBuilder::currentPoint() -{ - return m_traversalState.m_current; -} - -}
diff --git a/third_party/WebKit/Source/core/svg/SVGPathTraversalStateBuilder.h b/third_party/WebKit/Source/core/svg/SVGPathTraversalStateBuilder.h deleted file mode 100644 index d12af94..0000000 --- a/third_party/WebKit/Source/core/svg/SVGPathTraversalStateBuilder.h +++ /dev/null
@@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * Copyright (C) Research In Motion Limited 2010. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef SVGPathTraversalStateBuilder_h -#define SVGPathTraversalStateBuilder_h - -#include "core/svg/SVGPathConsumer.h" -#include "platform/graphics/PathTraversalState.h" - -namespace blink { - -class FloatPoint; - -class SVGPathTraversalStateBuilder final : public SVGPathConsumer { -public: - SVGPathTraversalStateBuilder(PathTraversalState::PathTraversalAction, float desiredLength = 0); - - unsigned pathSegmentIndex() const { return m_segmentIndex; } - float totalLength(); - FloatPoint currentPoint(); - - void incrementPathSegmentCount() override; - bool continueConsuming() override; - -private: - void emitSegment(const PathSegmentData&) override; - - PathTraversalState m_traversalState; - unsigned m_segmentIndex; -}; - -} // namespace blink - -#endif // SVGPathTraversalStateBuilder_h
diff --git a/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp b/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp index 907f8d1..e2920079 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp +++ b/third_party/WebKit/Source/core/svg/SVGPathUtilities.cpp
@@ -26,8 +26,6 @@ #include "core/svg/SVGPathParser.h" #include "core/svg/SVGPathStringBuilder.h" #include "core/svg/SVGPathStringSource.h" -#include "core/svg/SVGPathTraversalStateBuilder.h" -#include "platform/graphics/PathTraversalState.h" namespace blink { @@ -53,20 +51,19 @@ return parser.parsePathDataFromSource(NormalizedParsing); } -bool buildStringFromByteStream(const SVGPathByteStream& stream, String& result, PathParsingMode parsingMode) +String buildStringFromByteStream(const SVGPathByteStream& stream, PathParsingMode parsingMode) { if (stream.isEmpty()) - return true; + return String(); SVGPathStringBuilder builder; SVGPathByteStreamSource source(stream); SVGPathParser parser(&source, &builder); - bool ok = parser.parsePathDataFromSource(parsingMode); - result = builder.result(); - return ok; + parser.parsePathDataFromSource(parsingMode); + return builder.result(); } -bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream& result, PathParsingMode parsingMode) +bool buildByteStreamFromString(const String& d, SVGPathByteStream& result) { result.clear(); if (d.isEmpty()) @@ -78,45 +75,9 @@ SVGPathByteStreamBuilder builder(result); SVGPathStringSource source(d); SVGPathParser parser(&source, &builder); - bool ok = parser.parsePathDataFromSource(parsingMode); + bool ok = parser.parsePathDataFromSource(UnalteredParsing); result.shrinkToFit(); return ok; } -unsigned getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream& stream, float length) -{ - if (stream.isEmpty()) - return 0; - - SVGPathTraversalStateBuilder builder(PathTraversalState::TraversalSegmentAtLength, length); - SVGPathByteStreamSource source(stream); - SVGPathParser parser(&source, &builder); - parser.parsePathDataFromSource(NormalizedParsing); - return builder.pathSegmentIndex(); -} - -float getTotalLengthOfSVGPathByteStream(const SVGPathByteStream& stream) -{ - if (stream.isEmpty()) - return 0; - - SVGPathTraversalStateBuilder builder(PathTraversalState::TraversalTotalLength); - SVGPathByteStreamSource source(stream); - SVGPathParser parser(&source, &builder); - parser.parsePathDataFromSource(NormalizedParsing); - return builder.totalLength(); -} - -FloatPoint getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream& stream, float length) -{ - if (stream.isEmpty()) - return FloatPoint(); - - SVGPathTraversalStateBuilder builder(PathTraversalState::TraversalPointAtLength, length); - SVGPathByteStreamSource source(stream); - SVGPathParser parser(&source, &builder); - parser.parsePathDataFromSource(NormalizedParsing); - return builder.currentPoint(); -} - }
diff --git a/third_party/WebKit/Source/core/svg/SVGPathUtilities.h b/third_party/WebKit/Source/core/svg/SVGPathUtilities.h index 9f9ba6f49..601cee5 100644 --- a/third_party/WebKit/Source/core/svg/SVGPathUtilities.h +++ b/third_party/WebKit/Source/core/svg/SVGPathUtilities.h
@@ -22,7 +22,6 @@ #include "core/CoreExport.h" #include "core/svg/SVGPathParser.h" -#include "platform/geometry/FloatPoint.h" #include "wtf/text/WTFString.h" namespace blink { @@ -35,14 +34,10 @@ bool buildPathFromByteStream(const SVGPathByteStream&, Path&); // String -> SVGPathByteStream -bool buildSVGPathByteStreamFromString(const String&, SVGPathByteStream&, PathParsingMode); +bool buildByteStreamFromString(const String&, SVGPathByteStream&); // SVGPathByteStream -> String -bool buildStringFromByteStream(const SVGPathByteStream&, String&, PathParsingMode); - -unsigned getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream&, float length); -float getTotalLengthOfSVGPathByteStream(const SVGPathByteStream&); -FloatPoint getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream&, float length); +String buildStringFromByteStream(const SVGPathByteStream&, PathParsingMode); } // namespace blink
diff --git a/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp index 6b6a1d4..30688fb 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp
@@ -39,6 +39,7 @@ #include "core/loader/DocumentLoadTiming.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" +#include "core/paint/PaintTiming.h" #include "core/timing/PerformanceBase.h" #include "platform/network/ResourceLoadTiming.h" #include "platform/network/ResourceResponse.h" @@ -326,7 +327,7 @@ unsigned long long PerformanceTiming::firstPaint() const { - const DocumentTiming* timing = documentTiming(); + const PaintTiming* timing = paintTiming(); if (!timing) return 0; @@ -335,7 +336,7 @@ unsigned long long PerformanceTiming::firstTextPaint() const { - const DocumentTiming* timing = documentTiming(); + const PaintTiming* timing = paintTiming(); if (!timing) return 0; @@ -344,7 +345,7 @@ unsigned long long PerformanceTiming::firstImagePaint() const { - const DocumentTiming* timing = documentTiming(); + const PaintTiming* timing = paintTiming(); if (!timing) return 0; @@ -371,6 +372,18 @@ return &document->timing(); } +const PaintTiming* PerformanceTiming::paintTiming() const +{ + if (!m_frame) + return nullptr; + + Document* document = m_frame->document(); + if (!document) + return nullptr; + + return &PaintTiming::from(*document); +} + DocumentLoadTiming* PerformanceTiming::documentLoadTiming() const { DocumentLoader* loader = documentLoader();
diff --git a/third_party/WebKit/Source/core/timing/PerformanceTiming.h b/third_party/WebKit/Source/core/timing/PerformanceTiming.h index 15d5ab9..847b874 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceTiming.h +++ b/third_party/WebKit/Source/core/timing/PerformanceTiming.h
@@ -42,6 +42,7 @@ class DocumentLoader; class DocumentTiming; class LocalFrame; +class PaintTiming; class ResourceLoadTiming; class ScriptState; class ScriptValue; @@ -99,6 +100,7 @@ explicit PerformanceTiming(LocalFrame*); const DocumentTiming* documentTiming() const; + const PaintTiming* paintTiming() const; DocumentLoader* documentLoader() const; DocumentLoadTiming* documentLoadTiming() const; ResourceLoadTiming* resourceLoadTiming() const;
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp index 4a34b6a..adfe55e 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -32,6 +32,7 @@ #include "bindings/core/v8/ScheduledAction.h" #include "bindings/core/v8/ScriptSourceCode.h" #include "bindings/core/v8/ScriptValue.h" +#include "bindings/core/v8/V8AbstractEventListener.h" #include "bindings/core/v8/V8CacheOptions.h" #include "core/dom/ActiveDOMObject.h" #include "core/dom/AddConsoleMessageTask.h" @@ -211,6 +212,14 @@ // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects, // which become dangling once Heap is destroyed. + for (auto it = m_eventListeners.begin(); it != m_eventListeners.end(); ) { + RefPtrWillBeRawPtr<V8AbstractEventListener> listener = *it; + // clearListenerObject() will unregister the listener from + // m_eventListeners, and invalidate the iterator, so we have to advance + // it first. + ++it; + listener->clearListenerObject(); + } removeAllEventListeners(); clearScript(); @@ -324,6 +333,19 @@ return m_eventQueue.get(); } +void WorkerGlobalScope::registerEventListener(V8AbstractEventListener* eventListener) +{ + bool newEntry = m_eventListeners.add(eventListener).isNewEntry; + RELEASE_ASSERT(newEntry); +} + +void WorkerGlobalScope::deregisterEventListener(V8AbstractEventListener* eventListener) +{ + auto it = m_eventListeners.find(eventListener); + RELEASE_ASSERT(it != m_eventListeners.end()); + m_eventListeners.remove(it); +} + void WorkerGlobalScope::countFeature(UseCounter::Feature) const { // FIXME: How should we count features for shared/service workers? @@ -404,6 +426,7 @@ visitor->trace(m_timers); visitor->trace(m_messageStorage); visitor->trace(m_pendingMessages); + visitor->trace(m_eventListeners); HeapSupplementable<WorkerGlobalScope>::trace(visitor); #endif ExecutionContext::trace(visitor);
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h index 51da5e3..0a0c4cb 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -43,6 +43,7 @@ #include "platform/network/ContentSecurityPolicyParsers.h" #include "wtf/Assertions.h" #include "wtf/HashMap.h" +#include "wtf/ListHashSet.h" #include "wtf/OwnPtr.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -54,6 +55,7 @@ class ConsoleMessage; class ConsoleMessageStorage; class ExceptionState; +class V8AbstractEventListener; class WorkerClients; class WorkerConsole; class WorkerInspectorController; @@ -141,6 +143,9 @@ bool isSecureContext(String& errorMessage, const SecureContextCheck = StandardSecureContextCheck) const override; + void registerEventListener(V8AbstractEventListener*); + void deregisterEventListener(V8AbstractEventListener*); + DECLARE_VIRTUAL_TRACE(); protected: @@ -200,6 +205,7 @@ unsigned long m_workerExceptionUniqueIdentifier; WillBeHeapHashMap<unsigned long, RefPtrWillBeMember<ConsoleMessage>> m_pendingMessages; + WillBeHeapListHashSet<RefPtrWillBeMember<V8AbstractEventListener>> m_eventListeners; }; DEFINE_TYPE_CASTS(WorkerGlobalScope, ExecutionContext, context, context->isWorkerGlobalScope(), context.isWorkerGlobalScope());
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css b/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css index e249233..aebf5d4 100644 --- a/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css +++ b/third_party/WebKit/Source/devtools/front_end/accessibility/accessibilityNode.css
@@ -36,6 +36,7 @@ .ax-readable-name { flex-shrink: 0; + padding-left: 2px; } .ax-readable-string { @@ -59,7 +60,7 @@ } .tree-outline li { - padding-top: 5px; + padding-left: 1px; } .tree-outline li.invalid {
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js index edaa92d..6b37736 100644 --- a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js +++ b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
@@ -178,7 +178,7 @@ { if (this._uiMessage) this._uiMessage.remove(); - this._uiMessage = uiLocation.uiSourceCode.addMessage(this._level, this._text, uiLocation.lineNumber, uiLocation.columnNumber); + this._uiMessage = uiLocation.uiSourceCode.addLineMessage(this._level, this._text, uiLocation.lineNumber, uiLocation.columnNumber); }, dispose: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js index c64106d4..ab30fa6 100644 --- a/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js +++ b/third_party/WebKit/Source/devtools/front_end/bindings/ResourceScriptMapping.js
@@ -381,7 +381,7 @@ var compileError = errorData.compileError; if (compileError) { var messageText = WebInspector.UIString("LiveEdit compile failed: %s", compileError.message); - this._uiSourceCode.addMessage(WebInspector.UISourceCode.Message.Level.Error, messageText, compileError.lineNumber - 1, compileError.columnNumber + 1); + this._uiSourceCode.addLineMessage(WebInspector.UISourceCode.Message.Level.Error, messageText, compileError.lineNumber - 1, compileError.columnNumber + 1); } else { WebInspector.console.addMessage(WebInspector.UIString("Unknown LiveEdit error: %s; %s", JSON.stringify(errorData), error), warningLevel); }
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js index 3957871..ea6e837 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -49,7 +49,7 @@ this.element._section = this; this.registerRequiredCSS("components/objectValue.css"); this.registerRequiredCSS("components/objectPropertiesSection.css"); - this.rootElement().childrenListElement.classList.add("source-code", "object-properties-section") + this.rootElement().childrenListElement.classList.add("source-code", "object-properties-section"); } /** @const */ @@ -157,6 +157,7 @@ this.setExpandable(true); this.selectable = false; this.toggleOnClick = true; + this.listItemElement.classList.add("object-properties-section-root-element"); } WebInspector.ObjectPropertiesSection.RootElement.prototype = {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/eventListenersView.css b/third_party/WebKit/Source/devtools/front_end/components/eventListenersView.css index d8f52d7..d8a5af9 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/eventListenersView.css +++ b/third_party/WebKit/Source/devtools/front_end/components/eventListenersView.css
@@ -6,6 +6,7 @@ .event-listener-tree li { padding: 2px 0 0 5px; + overflow: hidden; } .event-listener-tree > li {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css b/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css index 002d4e6..e37a6ed 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css +++ b/third_party/WebKit/Source/devtools/front_end/components/objectPropertiesSection.css
@@ -20,6 +20,8 @@ .object-properties-section { padding: 0 0 0px 0px; color: rgb(33,33,33) !important; + display: flex; + flex-direction: column; } .object-properties-section li { @@ -50,3 +52,16 @@ .object-properties-section .synthetic-property { font-style: italic; } + +.object-properties-section-root-element { + display: flex; + flex-direction: row; +} + +.object-properties-section-root-element::before { + -webkit-mask-position: -4px -97px !important; +} + +.object-properties-section-root-element.expanded::before { + -webkit-mask-position: -20px -97px !important; +}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js index d07b2a7..0d53af95 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -663,7 +663,7 @@ treeElement.reveal(); var matches = treeElement.listItemElement.getElementsByClassName(WebInspector.highlightedSearchResultClassName); if (matches.length) - matches[0].scrollIntoViewIfNeeded(); + matches[0].scrollIntoViewIfNeeded(false); } }, @@ -1269,4 +1269,4 @@ }, __proto__: WebInspector.ThrottledWidget.prototype -} \ No newline at end of file +}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js index e3e3c67..ada997f 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
@@ -351,20 +351,6 @@ /** * @override - */ - onreveal: function() - { - if (this.listItemElement) { - var tagSpans = this.listItemElement.getElementsByClassName("webkit-html-tag-name"); - if (tagSpans.length) - tagSpans[0].scrollIntoViewIfNeeded(true); - else - this.listItemElement.scrollIntoViewIfNeeded(true); - } - }, - - /** - * @override * @param {boolean=} omitFocus * @param {boolean=} selectedByUser * @return {boolean}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/computedStyleSidebarPane.css b/third_party/WebKit/Source/devtools/front_end/elements/computedStyleSidebarPane.css index d88d954..65bf61c 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/computedStyleSidebarPane.css +++ b/third_party/WebKit/Source/devtools/front_end/elements/computedStyleSidebarPane.css
@@ -89,11 +89,6 @@ .tree-outline li::before { float: none; flex: none; - -webkit-mask-position: -3px -97px; background-color: rgb(110, 110, 110); margin-left: 4px; } - -.tree-outline li.parent.expanded::before { - -webkit-mask-position: -19px -97px; -}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css index 2591b7e..cd91788 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css +++ b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
@@ -25,8 +25,6 @@ } .elements-disclosure li.parent::before { - float: left; - width: 10px; box-sizing: border-box; } @@ -34,10 +32,10 @@ -webkit-user-select: none; -webkit-mask-image: url(Images/toolbarButtonGlyphs.png); -webkit-mask-size: 352px 168px; - content: "a"; + content: "aa"; color: transparent; text-shadow: none; - margin-right: 1px; + margin-right: -3px; } .elements-disclosure li.always-parent::before { @@ -325,6 +323,7 @@ .elements-disclosure .gutter-container { position: absolute; + top: 0; } .elements-disclosure li.selected .gutter-container:not(.has-decorations) {
diff --git a/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css b/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css index 08a6006..71947aed 100644 --- a/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css +++ b/third_party/WebKit/Source/devtools/front_end/inspectorStyle.css
@@ -46,10 +46,6 @@ color: #222; } -body.dark-theme { - -webkit-filter: invert(100%) hue-rotate(180deg) saturate(80%); -} - .platform-linux { color: rgb(48, 57, 66); font-family: Ubuntu, Arial, sans-serif; @@ -208,18 +204,13 @@ } .outline-disclosure li::before { - float: left; -webkit-user-select: none; -webkit-mask-image: url(Images/toolbarButtonGlyphs.png); -webkit-mask-size: 352px 168px; - content: "a"; + content: "aa"; color: transparent; text-shadow: none; - position: relative; - top: 2px; - margin-right: 1px; - width: 10px; - height: 10px; + margin-right: -2px; } .outline-disclosure li:not(.parent)::before { @@ -558,10 +549,6 @@ bottom: 0; } -body.dark-theme .root-view { - background: white; -} - .viewport-control-gap-element { color: transparent; }
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index 92d133a1..1a9a6fb 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -107,7 +107,6 @@ Runtime.experiments.register("applyCustomStylesheet", "Allow custom UI themes"); Runtime.experiments.register("blackboxJSFramesOnTimeline", "Blackbox JavaScript frames on Timeline", true); Runtime.experiments.register("colorContrastRatio", "Contrast ratio line in color picker", true); - Runtime.experiments.register("darkTheme", "Dark theme", true); Runtime.experiments.register("deviceMode", "Device mode", true); Runtime.experiments.register("emptySourceMapAutoStepping", "Empty sourcemap auto-stepping"); Runtime.experiments.register("fileSystemInspection", "FileSystem inspection"); @@ -168,9 +167,6 @@ WebInspector.initializeUIUtils(window); WebInspector.installComponentRootStyles(/** @type {!Element} */ (document.body)); - if (Runtime.experiments.isEnabled("darkTheme")) { - document.body.classList.add("dark-theme"); - } this._addMainEventListeners(document);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/requestHeadersView.css b/third_party/WebKit/Source/devtools/front_end/network/requestHeadersView.css index 56648a2..ccb48a3d 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/requestHeadersView.css +++ b/third_party/WebKit/Source/devtools/front_end/network/requestHeadersView.css
@@ -32,7 +32,7 @@ .request-headers-view .outline-disclosure li.parent::before { position: static; - width: 9px; + width: 13px; height: 9px; -webkit-mask-position: -4px -98px; background-image: none;
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js index 3f84a4b..8a427d9 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js
@@ -916,15 +916,6 @@ return false; }, - /** - * @override - */ - onreveal: function() - { - if (this.listItemElement) - this.listItemElement.scrollIntoViewIfNeeded(false); - }, - get titleText() { return this._titleText;
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/resourcesPanel.css b/third_party/WebKit/Source/devtools/front_end/resources/resourcesPanel.css index 1de8709..8b5a725 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/resourcesPanel.css +++ b/third_party/WebKit/Source/devtools/front_end/resources/resourcesPanel.css
@@ -36,6 +36,7 @@ .resources.panel .sidebar li { height: 18px; white-space: nowrap; + padding-top: 1px; } .resources.panel .sidebar li.selected { @@ -62,15 +63,16 @@ .resources.panel .sidebar .icon { width: 16px; height: 16px; - float: left; + position: relative; + top: 3px; + margin-top: -3px; } .resources.panel .base-storage-tree-element-title { overflow: hidden; - position: relative; text-overflow: ellipsis; padding-left: 2px; - top: 1px; + display: inline; } .resources-toolbar {
diff --git a/third_party/WebKit/Source/devtools/front_end/security/sidebar.css b/third_party/WebKit/Source/devtools/front_end/security/sidebar.css index 76217142..f6b5440 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/sidebar.css +++ b/third_party/WebKit/Source/devtools/front_end/security/sidebar.css
@@ -7,19 +7,19 @@ padding: 0; } +.tree-outline li { + display: flex; + flex-direction: row; + align-items: center; +} + .tree-outline:focus li.selected .lock-icon-neutral { background-color: #fff; } .tree-outline .security-main-view-sidebar-tree-item { border-bottom: 1px solid rgb(230, 230, 230); - padding-top: 0; -} - -.tree-outline .security-main-view-sidebar-tree-item .icon, -.tree-outline .security-main-view-sidebar-tree-item .titles { - margin-top: 1.5em; - margin-bottom: 1.5em; + padding: 16px 0; } .tree-outline .security-sidebar-origins { @@ -45,8 +45,8 @@ .tree-outline .sidebar-tree-item .lock-icon, .tree-outline .sidebar-tree-item .security-property { - float: left; margin-right: 2px; + flex: none; } .tree-outline:focus .security-sidebar-tree-item.selected .icon:not(.security-property-unknown) {
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js index a96afc8..21ce3b2 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptCompiler.js
@@ -73,7 +73,7 @@ } if (!exceptionDetails) return; - this._sourceFrame.uiSourceCode().addMessage(WebInspector.UISourceCode.Message.Level.Error, exceptionDetails.text, exceptionDetails.line - 1, exceptionDetails.column + 1); + this._sourceFrame.uiSourceCode().addLineMessage(WebInspector.UISourceCode.Message.Level.Error, exceptionDetails.text, exceptionDetails.line - 1, exceptionDetails.column + 1); this._compilationFinishedForTest(); } },
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js index 38f03e3..6b13bcf5 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
@@ -690,12 +690,6 @@ this.listItemElement.classList.add(this._iconClasses[i]); }, - onreveal: function() - { - if (this.listItemElement) - this.listItemElement.scrollIntoViewIfNeeded(true); - }, - /** * @return {string} */
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js index 31f806b..d8bce81 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js
@@ -125,7 +125,7 @@ if (!title || title === subtitle) subtitle = undefined; - var titleElement = createElementWithClass("div"); + var titleElement = createElementWithClass("div", "scope-chain-sidebar-pane-section-header"); titleElement.createChild("div", "scope-chain-sidebar-pane-section-subtitle").textContent = subtitle; titleElement.createChild("div", "scope-chain-sidebar-pane-section-title").textContent = title;
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js index 581d01f..ed1d00a 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -356,6 +356,7 @@ this._element.removeChildren(); this._objectPropertiesSection = null; if (!wasThrown && result && result.hasChildren && !result.customPreview()) { + headerElement.classList.add("watch-expression-object-header"); this._objectPropertiesSection = new WebInspector.ObjectPropertiesSection(result, headerElement); this._objectPresentationElement = this._objectPropertiesSection.element; var objectTreeElement = this._objectPropertiesSection.objectTreeElement();
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/navigatorView.css b/third_party/WebKit/Source/devtools/front_end/sources/navigatorView.css index 85119fa..9dbb3c91 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/navigatorView.css +++ b/third_party/WebKit/Source/devtools/front_end/sources/navigatorView.css
@@ -56,13 +56,14 @@ min-width: 100%; min-height: 100%; display: inline-block; - position: relative + position: relative; } .navigator li { height: 18px; line-height: 17px; white-space: nowrap; + padding-right: 3px; } .navigator :focus li.selected { @@ -80,7 +81,9 @@ .navigator .icon { width: 16px; height: 16px; - float: left; + margin-top: -2px; + position: relative; + top: 3px; } .navigator .base-navigator-tree-element-title {
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css b/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css index b6db1854..4a23d42 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css +++ b/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css
@@ -174,9 +174,14 @@ margin-left: 11px; } +.watch-expression-object-header .watch-expression-title { + margin-left: 1px; +} + .watch-expression { position: relative; padding: 1px 0px 1px 6px; + flex: none; } .watch-expressions .name { @@ -208,6 +213,15 @@ margin-left: 12px; } +.watch-expression-header { + flex: auto; +} + +.watch-expression-object-header { + margin-left: -12px; + padding-left: 12px; +} + .watch-expression-header:hover { background-color: #F0F0F0; padding-right: 14px; @@ -217,6 +231,10 @@ margin-top: 0px; } +.scope-chain-sidebar-pane-section-header { + flex: auto; +} + .scope-chain-sidebar-pane-section-subtitle { float: right; margin-left: 5px;
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js index 17b82a87..de8550c0 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
@@ -938,6 +938,26 @@ }, /** + * @override + * @param {number} index + * @return {?Array<!{title: string, value: (string|!Element)}>} + */ + prepareHighlightedEntryInfo: function(index) + { + var /** @const */ maxURLChars = 80; + var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */ (this._requests[index]); + if (!request.url) + return null; + var value = createElement("div"); + var duration = request.endTime - request.startTime; + if (request.startTime && isFinite(duration)) + value.createChild("span", "timeline-network-info-duration").textContent = Number.millisToString(duration); + value.createChild("span", "timeline-network-info-method").textContent = request.requestMethod; + value.createChild("span", "timeline-network-info-url").textContent = request.url.trimMiddle(maxURLChars); + return [{ title: "", value: value }]; + }, + + /** * @param {!Array.<!WebInspector.TracingModel.Event>} events */ _appendTimelineData: function(events)
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js index 63529f4..6e3e5fc5 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -65,6 +65,14 @@ }, /** + * @return {boolean} + */ + _exposePercentages: function() + { + return false; + }, + + /** * @param {!Element} parent */ _populateToolbar: function(parent) { }, @@ -185,6 +193,9 @@ _updateDetailsForSelection: function() { + // FIXME: remove this as we implement details for all modes. + if (!this._detailsView) + return; var selectedNode = this._dataGrid.selectedNode ? /** @type {!WebInspector.TimelineTreeView.GridNode} */ (this._dataGrid.selectedNode)._profileNode : null; if (selectedNode === this._lastSelectedNode) return; @@ -333,25 +344,9 @@ { if (columnIdentifier !== "self" && columnIdentifier !== "total" && columnIdentifier !== "startTime") return null; - /** - * @param {number} time - * @return {string} - */ - function formatMilliseconds(time) - { - return WebInspector.UIString("%.1f\u2009ms", time); - } - /** - * @param {number} value - * @return {string} - */ - function formatPercent(value) - { - return WebInspector.UIString("%.1f\u2009%%", value); - } + var showPercents = false; var value; - var percentText; var maxTime; switch (columnIdentifier) { case "startTime": @@ -359,13 +354,13 @@ break; case "self": value = this._profileNode.selfTime; - percentText = formatPercent(this._profileNode.selfTime / this._grandTotalTime * 100); maxTime = this._maxSelfTime; + showPercents = true; break; case "total": value = this._profileNode.totalTime; - percentText = formatPercent(this._profileNode.totalTime / this._grandTotalTime * 100); maxTime = this._maxTotalTime; + showPercents = true; break; default: return null; @@ -373,13 +368,14 @@ var cell = this.createTD(columnIdentifier); cell.className = "numeric-column"; var textDiv = cell.createChild("div"); - textDiv.createChild("span").textContent = formatMilliseconds(value); - if (percentText) { - textDiv.createChild("span", "percent-column").textContent = percentText; - textDiv.classList.add("profile-multiple-values"); - } - if (maxTime) + textDiv.createChild("span").textContent = WebInspector.UIString("%.1f\u2009ms", value); + + if (showPercents && this._treeView._exposePercentages()) + textDiv.createChild("span", "percent-column").textContent = WebInspector.UIString("%.1f\u2009%%", value / this._grandTotalTime * 100); + if (maxTime) { + textDiv.classList.add("background-percent-bar"); cell.createChild("div", "background-bar-container").createChild("div", "background-bar").style.width = (value * 100 / maxTime).toFixed(1) + "%"; + } return cell; }, @@ -472,6 +468,15 @@ panelToolbar.appendToolbarItem(this._groupByCombobox); }, + /** + * @override + * @return {boolean} + */ + _exposePercentages: function() + { + return true; + }, + _onGroupByChanged: function() { this._groupBySetting.set(this._groupByCombobox.selectedOption().value);
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css index 515ccde..0c70f73 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css +++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -971,7 +971,7 @@ position: relative; } -.timeline-tree-view .data-grid div.profile-multiple-values { +.timeline-tree-view .data-grid div.background-percent-bar { float: right; }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SidebarTreeElement.js b/third_party/WebKit/Source/devtools/front_end/ui/SidebarTreeElement.js index 9259239..f18b890 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/SidebarTreeElement.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/SidebarTreeElement.js
@@ -62,12 +62,6 @@ this.listItemElement.classList.add("sidebar-tree-section"); }, - onreveal: function() - { - if (this.listItemElement) - this.listItemElement.scrollIntoViewIfNeeded(false); - }, - __proto__: TreeElement.prototype } @@ -182,11 +176,5 @@ this.listItemElement.appendChildren(this.iconElement, this.statusElement, this.titlesElement); }, - onreveal: function() - { - if (this.listItemElement) - this.listItemElement.scrollIntoViewIfNeeded(false); - }, - __proto__: TreeElement.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.css b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.css index f7f6ce0..cf51574 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.css
@@ -65,7 +65,6 @@ .tree-outline li { text-overflow: ellipsis; white-space: nowrap; - overflow: hidden; min-height: 17px; padding-top: 2px; position: relative; @@ -80,18 +79,14 @@ } .tree-outline li::before { - float: left; -webkit-user-select: none; -webkit-mask-image: url(Images/toolbarButtonGlyphs.png); -webkit-mask-size: 352px 168px; - content: "a"; + content: "aa"; color: transparent; text-shadow: none; - position: relative; - margin-right: 1px; - top: 1px; - width: 10px; - height: 10px; + margin-right: -2px; + height: 12px; } .tree-outline li:not(.parent)::before {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js index c8f4645..a92882c 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js
@@ -286,6 +286,27 @@ event.consume(true); }, + /** + * @param {!TreeElement} treeElement + * @param {boolean} center + */ + _deferredScrollIntoView: function(treeElement, center) + { + if (!this._treeElementToScrollIntoView) + this.element.window().requestAnimationFrame(deferredScrollIntoView.bind(this)); + this._treeElementToScrollIntoView = treeElement; + this._centerUponScrollIntoView = center; + /** + * @this {TreeOutline} + */ + function deferredScrollIntoView() + { + this._treeElementToScrollIntoView.listItemElement.scrollIntoViewIfNeeded(this._centerUponScrollIntoView); + delete this._treeElementToScrollIntoView; + delete this._centerUponScrollIntoView; + } + }, + __proto__: WebInspector.Object.prototype } @@ -852,7 +873,10 @@ } }, - reveal: function() + /** + * @param {boolean=} center + */ + reveal: function(center) { var currentAncestor = this.parent; while (currentAncestor && !currentAncestor.root) { @@ -861,9 +885,7 @@ currentAncestor = currentAncestor.parent; } - this.listItemElement.scrollIntoViewIfNeeded(); - - this.onreveal(); + this.treeOutline._deferredScrollIntoView(this, !!center); }, /** @@ -923,7 +945,7 @@ */ revealAndSelect: function(omitFocus) { - this.reveal(); + this.reveal(true); this.select(omitFocus); }, @@ -1006,10 +1028,6 @@ return false; }, - onreveal: function() - { - }, - /** * @param {boolean=} selectedByUser * @return {boolean}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js index 3163b9a..a885cad 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js
@@ -543,6 +543,7 @@ _animationCompleted: function() { delete this._cancelWindowTimesAnimation; + this._hideHighlight(); }, /** @@ -592,6 +593,7 @@ this._dragStartWindowLeft = this._timeWindowLeft; this._dragStartWindowRight = this._timeWindowRight; this._canvas.style.cursor = ""; + this._hideHighlight(); return true; }, @@ -634,6 +636,7 @@ style.width = "1px"; this._selectedTimeSpanLabel.textContent = ""; this._selectionOverlay.classList.remove("hidden"); + this._hideHighlight(); return true; }, @@ -681,6 +684,7 @@ _onMouseMove: function(event) { this._lastMouseOffsetX = event.offsetX; + this._lastMouseOffsetY = event.offsetY; if (!this._enabled()) return; @@ -691,41 +695,60 @@ var inDividersBar = event.offsetY < WebInspector.FlameChart.DividersBarHeight; this._highlightedMarkerIndex = inDividersBar ? this._markerIndexAtPosition(event.offsetX) : -1; this._updateMarkerHighlight(); - - this._highlightEntry(this._coordinatesToEntryIndex(event.offsetX, event.offsetY)); + this._showHighlight(); }, _onMouseOut: function() { - this._highlightEntry(-1); + this._hideHighlight(); }, - /** - * @param {number} entryIndex - */ - _highlightEntry: function(entryIndex) + _showHighlight: function() { - if (this._highlightedEntryIndex === entryIndex) + var entryIndex = this._coordinatesToEntryIndex(this._lastMouseOffsetX, this._lastMouseOffsetY); + if (entryIndex === -1) { + this._hideHighlight(); return; - - if (entryIndex === -1 || !this._dataProvider.canJumpToEntry(entryIndex)) - this._canvas.style.cursor = "default"; - else - this._canvas.style.cursor = "pointer"; - - this._highlightedEntryIndex = entryIndex; - - this._updateElementPosition(this._highlightElement, this._highlightedEntryIndex); - this._entryInfo.removeChildren(); - - if (this._highlightedEntryIndex === -1) - return; - - if (!this._isDragging) { - var entryInfo = this._dataProvider.prepareHighlightedEntryInfo(this._highlightedEntryIndex); + } + if (entryIndex !== this._highlightedEntryIndex) { + this._entryInfo.removeChildren(); + var entryInfo = this._dataProvider.prepareHighlightedEntryInfo(entryIndex); if (entryInfo) this._entryInfo.appendChild(this._buildEntryInfo(entryInfo)); } + var mouseX = this._lastMouseOffsetX; + var mouseY = this._lastMouseOffsetY; + var parentWidth = this._entryInfo.parentElement.clientWidth; + var parentHeight = this._entryInfo.parentElement.clientHeight; + var infoWidth = this._entryInfo.clientWidth; + var infoHeight = this._entryInfo.clientHeight; + var /** @const */ offsetX = 10; + var /** @const */ offsetY = 6; + var x; + var y; + for (var quadrant = 0; quadrant < 4; ++quadrant) { + var dx = quadrant & 2 ? -offsetX - infoWidth : offsetX; + var dy = quadrant & 1 ? -offsetY - infoHeight : offsetY; + x = Number.constrain(mouseX + dx, 0, parentWidth - infoWidth); + y = Number.constrain(mouseY + dy, 0, parentHeight - infoHeight); + if (x >= mouseX || mouseX >= x + infoWidth || y >= mouseY || mouseY >= y + infoHeight) + break; + } + this._entryInfo.style.left = x + "px"; + this._entryInfo.style.top = y + "px"; + if (this._highlightedEntryIndex === entryIndex) + return; + this._highlightedEntryIndex = entryIndex; + this._canvas.style.cursor = this._dataProvider.canJumpToEntry(entryIndex) ? "pointer" : "default"; + this._updateElementPosition(this._highlightElement, this._highlightedEntryIndex); + }, + + _hideHighlight: function() + { + this._entryInfo.removeChildren(); + this._canvas.style.cursor = "default"; + this._highlightedEntryIndex = -1; + this._updateElementPosition(this._highlightElement, this._highlightedEntryIndex); }, _onClick: function() @@ -1395,7 +1418,10 @@ for (var entry of entryInfo) { var row = infoTable.createChild("tr"); row.createChild("td", "title").textContent = entry.title; - row.createChild("td").textContent = typeof entry.value === "string" ? entry.value : entry.value.textContent; + if (typeof entry.value === "string") + row.createChild("td").textContent = entry.value; + else + row.createChild("td").appendChild(entry.value); } return infoTable; }, @@ -1508,6 +1534,7 @@ _onScroll: function() { this._scrollTop = this._vScrollElement.scrollTop; + this._hideHighlight(); this.scheduleUpdate(); },
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/flameChart.css b/third_party/WebKit/Source/devtools/front_end/ui_lazy/flameChart.css index 30d588f..e54ca61 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/flameChart.css +++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/flameChart.css
@@ -59,15 +59,36 @@ bottom: 0; } -.flame-chart-entry-info { +.flame-chart-entry-info:not(:empty) { + z-index: 200; position: absolute; - bottom: 6px; - left: 12px; - background-color: rgba(255, 255, 255, 0.7); + background-color: white; pointer-events: none; + padding: 2px; + box-shadow: hsla(0, 0%, 0%, 0.4) 1px 1px 8px; +} + +.flame-chart-entry-info table tr td:empty { + padding: 0; +} + +.flame-chart-entry-info table tr td:not(:empty) { + padding: 0 5px; + white-space: nowrap; } .flame-chart-entry-info table tr td:first-child { font-weight: bold; - padding-right: 8px; +} + +.flame-chart-entry-info table tr td span { + margin-right: 5px; +} + +.flame-chart-entry-info table tr td span.timeline-network-info-duration { + color: darkgreen; +} + +.flame-chart-entry-info table tr td span.timeline-network-info-method { + color: darkblue; }
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js index 9e5d61a..80e9b53 100644 --- a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js +++ b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
@@ -596,9 +596,20 @@ * @param {number=} columnNumber * @return {!WebInspector.UISourceCode.Message} message */ - addMessage: function(level, text, lineNumber, columnNumber) + addLineMessage: function(level, text, lineNumber, columnNumber) { - var message = new WebInspector.UISourceCode.Message(this, level, text, lineNumber, columnNumber); + return this.addMessage(level, text, new WebInspector.TextRange(lineNumber, columnNumber || 0, lineNumber, columnNumber || 0)); + }, + + /** + * @param {!WebInspector.UISourceCode.Message.Level} level + * @param {string} text + * @param {!WebInspector.TextRange} range + * @return {!WebInspector.UISourceCode.Message} message + */ + addMessage: function(level, text, range) + { + var message = new WebInspector.UISourceCode.Message(this, level, text, range); this._messages.push(message); this.dispatchEventToListeners(WebInspector.UISourceCode.Events.MessageAdded, message); return message; @@ -765,16 +776,14 @@ * @param {!WebInspector.UISourceCode} uiSourceCode * @param {!WebInspector.UISourceCode.Message.Level} level * @param {string} text - * @param {number} lineNumber - * @param {number=} columnNumber + * @param {!WebInspector.TextRange} range */ -WebInspector.UISourceCode.Message = function(uiSourceCode, level, text, lineNumber, columnNumber) +WebInspector.UISourceCode.Message = function(uiSourceCode, level, text, range) { this._uiSourceCode = uiSourceCode; this._level = level; this._text = text; - this._lineNumber = lineNumber; - this._columnNumber = columnNumber; + this._range = range; } /** @@ -811,11 +820,18 @@ }, /** + * @return {!WebInspector.TextRange} + */ + range: function() { + return this._range; + }, + + /** * @return {number} */ lineNumber: function() { - return this._lineNumber; + return this._range.startLine; }, /** @@ -823,7 +839,7 @@ */ columnNumber: function() { - return this._columnNumber; + return this._range.startColumn; }, /** @@ -832,7 +848,7 @@ */ isEqual: function(another) { - return this._uiSourceCode === another._uiSourceCode && this.text() === another.text() && this.level() === another.level() && this.lineNumber() === another.lineNumber() && this.columnNumber() === another.columnNumber(); + return this._uiSourceCode === another._uiSourceCode && this.text() === another.text() && this.level() === another.level() && this.range().equal(another.range()); }, remove: function()
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp index 0569076b..4211da1 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -595,22 +595,17 @@ // find out if this element is inside of a label element. // if so, it may be ignored because it's the label for a checkbox or radio button AXObject* controlObject = correspondingControlForLabelElement(); - if (controlObject && controlObject->isCheckboxOrRadio()) { - AXNameFrom controlNameFrom; - AXObject::AXObjectVector controlNameObjects; - controlObject->name(controlNameFrom, &controlNameObjects); - if (controlNameFrom == AXNameFromRelatedElement) { - if (ignoredReasons) { - HTMLLabelElement* label = labelElementContainer(); - if (label && !label->isSameNode(node())) { - AXObject* labelAXObject = axObjectCache().getOrCreate(label); - ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXObject)); - } - - ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); + if (controlObject && controlObject->isCheckboxOrRadio() && controlObject->nameFromLabelElement()) { + if (ignoredReasons) { + HTMLLabelElement* label = labelElementContainer(); + if (label && !label->isSameNode(node())) { + AXObject* labelAXObject = axObjectCache().getOrCreate(label); + ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXObject)); } - return true; + + ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); } + return true; } if (m_layoutObject->isBR()) @@ -1501,13 +1496,8 @@ // If this element is the label of a control, a hit test should return the control. if (result->isAXLayoutObject()) { AXObject* controlObject = toAXLayoutObject(result)->correspondingControlForLabelElement(); - if (controlObject) { - AXNameFrom controlNameFrom; - AXObject::AXObjectVector controlNameObjects; - controlObject->name(controlNameFrom, &controlNameObjects); - if (controlObject && controlNameFrom == AXNameFromRelatedElement) - return controlObject; - } + if (controlObject && controlObject->nameFromLabelElement()) + return controlObject; } result = result->parentObjectUnignored();
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp index 001fcef..2e73403 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -173,22 +173,17 @@ // Ignore labels that are already referenced by a control. AXObject* controlObject = correspondingControlForLabelElement(); - if (controlObject && controlObject->isCheckboxOrRadio()) { - AXNameFrom controlNameFrom; - AXObject::AXObjectVector controlNameObjects; - controlObject->name(controlNameFrom, &controlNameObjects); - if (controlNameFrom == AXNameFromRelatedElement) { - if (ignoredReasons) { - HTMLLabelElement* label = labelElementContainer(); - if (label && !label->isSameNode(node())) { - AXObject* labelAXObject = axObjectCache().getOrCreate(label); - ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXObject)); - } - - ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); + if (controlObject && controlObject->isCheckboxOrRadio() && controlObject->nameFromLabelElement()) { + if (ignoredReasons) { + HTMLLabelElement* label = labelElementContainer(); + if (label && !label->isSameNode(node())) { + AXObject* labelAXObject = axObjectCache().getOrCreate(label); + ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXObject)); } - return true; + + ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); } + return true; } Element* element = node()->isElementNode() ? toElement(node()) : node()->parentElement(); @@ -1616,6 +1611,47 @@ return accumulatedText.toString(); } +bool AXNodeObject::nameFromLabelElement() const +{ + // This unfortunately duplicates a bit of logic from textAlternative and nativeTextAlternative, + // but it's necessary because nameFromLabelElement needs to be called from + // computeAccessibilityIsIgnored, which isn't allowed to call axObjectCache->getOrCreate. + + if (!node() && !layoutObject()) + return false; + + // Step 2A from: http://www.w3.org/TR/accname-aam-1.1 + if (layoutObject() + && layoutObject()->style()->visibility() != VISIBLE + && !equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) { + return false; + } + + // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 + WillBeHeapVector<RawPtrWillBeMember<Element>> elements; + ariaLabelledbyElementVector(elements); + if (elements.size() > 0) + return false; + + // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 + const AtomicString& ariaLabel = getAttribute(aria_labelAttr); + if (!ariaLabel.isEmpty()) + return false; + + // Based on http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and-description-calculation + // 5.1/5.5 Text inputs, Other labelable Elements + HTMLElement* htmlElement = nullptr; + if (node()->isHTMLElement()) + htmlElement = toHTMLElement(node()); + if (htmlElement && htmlElement->isLabelable()) { + HTMLLabelElement* label = labelForElement(htmlElement); + if (label) + return true; + } + + return false; +} + LayoutRect AXNodeObject::elementRect() const { // First check if it has a custom rect, for example if this element is tied to a canvas path. @@ -2065,6 +2101,7 @@ inputElement = toHTMLInputElement(node()); // 5.1/5.5 Text inputs, Other labelable Elements + // If you change this logic, update AXNodeObject::nameFromLabelElement, too. HTMLElement* htmlElement = nullptr; if (node()->isHTMLElement()) htmlElement = toHTMLElement(node());
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h index e9c54f5..7ce6133a 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h +++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.h
@@ -161,6 +161,7 @@ String description(AXNameFrom, AXDescriptionFrom&, AXObjectVector* descriptionObjects) const override; String description(AXNameFrom, AXDescriptionFrom&, DescriptionSources*, AXRelatedObjectVector*) const override; String placeholder(AXNameFrom, AXDescriptionFrom) const override; + bool nameFromLabelElement() const override; // Location and click point in frame-relative coordinates. LayoutRect elementRect() const override;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp index 5dd1f4cd..29df97c 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -723,6 +723,7 @@ visited.add(this); // Step 2A from: http://www.w3.org/TR/accname-aam-1.1 + // If you change this logic, update AXNodeObject::nameFromLabelElement, too. if (!recursive && layoutObject() && layoutObject()->style()->visibility() != VISIBLE && !equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) { @@ -730,6 +731,7 @@ } // Step 2B from: http://www.w3.org/TR/accname-aam-1.1 + // If you change this logic, update AXNodeObject::nameFromLabelElement, too. if (!inAriaLabelledByTraversal && !alreadyVisited) { const QualifiedName& attr = hasAttribute(aria_labeledbyAttr) && !hasAttribute(aria_labelledbyAttr) ? aria_labeledbyAttr : aria_labelledbyAttr; nameFrom = AXNameFromRelatedElement; @@ -763,6 +765,7 @@ } // Step 2C from: http://www.w3.org/TR/accname-aam-1.1 + // If you change this logic, update AXNodeObject::nameFromLabelElement, too. nameFrom = AXNameFromAttribute; if (nameSources) { nameSources->append(NameSource(*foundTextAlternative, aria_labelAttr));
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h index 431c4d3..03f0f19 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.h +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -704,6 +704,11 @@ // This is a simpler high-level interface to |name| used by Inspector. String computedName() const; + // Internal function used to determine whether the result of calling |name| on this object would + // return text that came from the an HTML label element or not. This is intended to be faster than calling + // |name| or |textAlternative|, and without side effects (it won't call axObjectCache->getOrCreate). + virtual bool nameFromLabelElement() const { return false; } + // // Properties of static elements. //
diff --git a/third_party/WebKit/Source/modules/canvas2d/Path2D.idl b/third_party/WebKit/Source/modules/canvas2d/Path2D.idl index f77f06d..2d83628 100644 --- a/third_party/WebKit/Source/modules/canvas2d/Path2D.idl +++ b/third_party/WebKit/Source/modules/canvas2d/Path2D.idl
@@ -33,9 +33,10 @@ Constructor(Path2D path), Constructor(DOMString text), GarbageCollected, + TypeChecking=Interface, ] interface Path2D { - [RuntimeEnabled=ExperimentalCanvasFeatures, TypeChecking=Interface] void addPath(Path2D path, optional SVGMatrix? transform); + [RuntimeEnabled=ExperimentalCanvasFeatures] void addPath(Path2D path, optional SVGMatrix? transform); }; Path2D implements CanvasPathMethods;
diff --git a/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp b/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp index d916a050..0c1193b 100644 --- a/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp +++ b/third_party/WebKit/Source/modules/notifications/ServiceWorkerRegistrationNotifications.cpp
@@ -60,6 +60,9 @@ if (exceptionState.hadException()) return exceptionState.reject(scriptState); + // Log number of actions developer provided in linear histogram: 0 -> underflow bucket, 1-16 -> distinct buckets, 17+ -> overflow bucket. + Platform::current()->histogramEnumeration("Notifications.PersistentNotificationActionCount", options.actions().size(), 17); + ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise();
diff --git a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp index fbf90f8..9b627c3 100644 --- a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp
@@ -82,8 +82,8 @@ // Constructor for rendering to the audio hardware. AbstractAudioContext::AbstractAudioContext(Document* document) : ActiveDOMObject(document) - , m_isCleared(false) , m_destinationNode(nullptr) + , m_isCleared(false) , m_isResolvingResumePromises(false) , m_connectionCount(0) , m_didInitializeContextGraphMutex(false) @@ -99,8 +99,8 @@ // Constructor for offline (non-realtime) rendering. AbstractAudioContext::AbstractAudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) : ActiveDOMObject(document) - , m_isCleared(false) , m_destinationNode(nullptr) + , m_isCleared(false) , m_isResolvingResumePromises(false) , m_connectionCount(0) , m_didInitializeContextGraphMutex(false) @@ -108,12 +108,6 @@ , m_contextState(Suspended) { m_didInitializeContextGraphMutex = true; - // Create a new destination for offline rendering. - m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate); - if (m_renderTarget.get()) - m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get()); - - initialize(); } AbstractAudioContext::~AbstractAudioContext() @@ -804,34 +798,8 @@ } } -void AbstractAudioContext::fireCompletionEvent() -{ - ASSERT(isMainThread()); - if (!isMainThread()) - return; - - AudioBuffer* renderedBuffer = m_renderTarget.get(); - - // For an offline context, we set the state to closed here so that the oncomplete handler sees - // that the context has been closed. - setContextState(Closed); - - ASSERT(renderedBuffer); - if (!renderedBuffer) - return; - - // Avoid firing the event if the document has already gone away. - if (executionContext()) { - // Call the offline rendering completion event listener and resolve the promise too. - dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); - m_offlineResolver->resolve(renderedBuffer); - } -} - DEFINE_TRACE(AbstractAudioContext) { - visitor->trace(m_offlineResolver); - visitor->trace(m_renderTarget); visitor->trace(m_destinationNode); visitor->trace(m_listener); // trace() can be called in AbstractAudioContext constructor, and
diff --git a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h index 10c587f..79cc3122 100644 --- a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h
@@ -167,8 +167,10 @@ // Close virtual ScriptPromise closeContext(ScriptState*) = 0; - // Suspend/Resume + // Suspend virtual ScriptPromise suspendContext(ScriptState*) = 0; + + // Resume virtual ScriptPromise resumeContext(ScriptState*) = 0; // When a source node has started processing and needs to be protected, @@ -227,11 +229,9 @@ const AtomicString& interfaceName() const final; ExecutionContext* executionContext() const final; - DEFINE_ATTRIBUTE_EVENT_LISTENER(complete); DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange); void startRendering(); - void fireCompletionEvent(); void notifyStateChange(); // A context is considered closed if: @@ -246,20 +246,27 @@ explicit AbstractAudioContext(Document*); AbstractAudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); - void setContextState(AudioContextState); - virtual void didClose() {} + void initialize(); void uninitialize(); - Member<ScriptPromiseResolver> m_offlineResolver; + void setContextState(AudioContextState); + + virtual void didClose() {} + + // Tries to handle AudioBufferSourceNodes that were started but became disconnected or was never + // connected. Because these never get pulled anymore, they will stay around forever. So if we + // can, try to stop them so they can be collected. + void handleStoppableSourceNodes(); + + Member<AudioDestinationNode> m_destinationNode; // FIXME(dominicc): Move m_resumeResolvers to AudioContext, because only // it creates these Promises. // Vector of promises created by resume(). It takes time to handle them, so we collect all of // the promises here until they can be resolved or rejected. HeapVector<Member<ScriptPromiseResolver>> m_resumeResolvers; -private: - void initialize(); +private: bool m_isCleared; void clear(); @@ -269,7 +276,6 @@ // haven't finished playing. Make sure to release them here. void releaseActiveSourceNodes(); - Member<AudioDestinationNode> m_destinationNode; Member<AudioListener> m_listener; // Only accessed in the audio thread. @@ -304,18 +310,11 @@ bool m_didInitializeContextGraphMutex; RefPtr<DeferredTaskHandler> m_deferredTaskHandler; - Member<AudioBuffer> m_renderTarget; - // The state of the AbstractAudioContext. AudioContextState m_contextState; AsyncAudioDecoder m_audioDecoder; - // Tries to handle AudioBufferSourceNodes that were started but became disconnected or was never - // connected. Because these never get pulled anymore, they will stay around forever. So if we - // can, try to stop them so they can be collected. - void handleStoppableSourceNodes(); - // This is considering 32 is large enough for multiple channels audio. // It is somewhat arbitrary and could be increased if necessary. enum { MaxNumberOfChannels = 32 };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp index bc863ca..36b73d8 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "config.h" +#if ENABLE(WEB_AUDIO) #include "modules/webaudio/AudioBasicProcessorHandler.h" #include "core/testing/DummyPageHolder.h" @@ -52,3 +53,5 @@ } } // namespace blink + +#endif // ENABLE(WEB_AUDIO)
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp index ccd7d3b6..c00b959 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
@@ -43,10 +43,10 @@ namespace blink { AudioHandler::AudioHandler(NodeType nodeType, AudioNode& node, float sampleRate) - : m_isInitialized(false) + : m_context(node.context()) + , m_isInitialized(false) , m_nodeType(NodeTypeUnknown) , m_node(&node) - , m_context(node.context()) , m_sampleRate(sampleRate) , m_lastProcessingTime(-1) , m_lastNonSilentTime(-1)
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.h b/third_party/WebKit/Source/modules/webaudio/AudioNode.h index 53c2b67d..49e2aa3d 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
@@ -107,7 +107,7 @@ // nullptr otherwise. This always returns a valid object in an audio // rendering thread, and inside dispose(). We must not call context() in // the destructor. - AbstractAudioContext* context() const; + virtual AbstractAudioContext* context() const; void clearContext() { m_context = nullptr; } enum ChannelCountMode { @@ -229,6 +229,12 @@ // Force all inputs to take any channel interpretation changes into account. void updateChannelsForInputs(); + // This raw pointer is safe because this is cleared for all of live + // AudioHandlers when the AbstractAudioContext dies. Do not access m_context + // directly, use context() instead. + GC_PLUGIN_IGNORE("http://crbug.com/404527") + AbstractAudioContext* m_context; + private: void setNodeType(NodeType); @@ -241,12 +247,6 @@ GC_PLUGIN_IGNORE("http://crbug.com/404527") AudioNode* m_node; - // This raw pointer is safe because this is cleared for all of live - // AudioHandlers when the AbstractAudioContext dies. Do not access m_context - // directly, use context() instead. - GC_PLUGIN_IGNORE("http://crbug.com/404527") - AbstractAudioContext* m_context; - float m_sampleRate; Vector<OwnPtr<AudioNodeInput>> m_inputs; Vector<OwnPtr<AudioNodeOutput>> m_outputs;
diff --git a/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp index ac2843a..c7b94600 100644 --- a/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "config.h" +#if ENABLE(WEB_AUDIO) #include "modules/webaudio/ConvolverNode.h" #include "core/testing/DummyPageHolder.h" @@ -27,3 +28,5 @@ } } // namespace blink + +#endif // ENABLE(WEB_AUDIO)
diff --git a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp index 3086c03..ed32c4b 100644 --- a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp +++ b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
@@ -28,6 +28,7 @@ #include "modules/webaudio/AudioNode.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/OfflineAudioContext.h" #include "platform/ThreadSafeFunctional.h" #include "public/platform/Platform.h" #include "wtf/MainThread.h" @@ -60,6 +61,17 @@ m_contextGraphMutex.unlock(); } +void DeferredTaskHandler::offlineLock() +{ + // RELEASE_ASSERT is here to make sure to explicitly crash if this is called + // from other than the offline render thread, which is considered as the + // audio thread in OfflineAudioContext. + RELEASE_ASSERT_WITH_MESSAGE(isAudioThread(), + "DeferredTaskHandler::offlineLock() must be called within the offline audio thread."); + + m_contextGraphMutex.lock(); +} + #if ENABLE(ASSERT) bool DeferredTaskHandler::isGraphOwner() { @@ -232,6 +244,12 @@ m_handler.lock(); } +DeferredTaskHandler::OfflineGraphAutoLocker::OfflineGraphAutoLocker(OfflineAudioContext* context) + : m_handler(context->deferredTaskHandler()) +{ + m_handler.offlineLock(); +} + void DeferredTaskHandler::addRenderingOrphanHandler(PassRefPtr<AudioHandler> handler) { ASSERT(handler);
diff --git a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h index b145642b..184ee1c 100644 --- a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h +++ b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h
@@ -38,6 +38,7 @@ namespace blink { class AbstractAudioContext; +class OfflineAudioContext; class AudioHandler; class AudioNodeOutput; class AudioSummingJunction; @@ -110,6 +111,11 @@ void lock(); bool tryLock(); void unlock(); + + // This locks the audio render thread for OfflineAudioContext rendering. + // MUST NOT be used in the real-time audio context. + void offlineLock(); + #if ENABLE(ASSERT) // Returns true if this thread owns the context's lock. bool isGraphOwner(); @@ -131,6 +137,21 @@ DeferredTaskHandler& m_handler; }; + // This is for locking offline render thread (which is considered as the + // audio thread) with unlocking on self-destruction at the end of the scope. + // Also note that it uses lock() rather than tryLock() because the timing + // MUST be accurate on offline rendering. + class MODULES_EXPORT OfflineGraphAutoLocker { + STACK_ALLOCATED(); + public: + explicit OfflineGraphAutoLocker(OfflineAudioContext*); + + ~OfflineGraphAutoLocker() { m_handler.unlock(); } + + private: + DeferredTaskHandler& m_handler; + }; + private: DeferredTaskHandler(); void updateAutomaticPullNodes();
diff --git a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp index 85c9a36..c11e4fad 100644 --- a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "config.h" +#if ENABLE(WEB_AUDIO) #include "modules/webaudio/DynamicsCompressorNode.h" #include "core/testing/DummyPageHolder.h" @@ -27,3 +28,5 @@ } } // namespace blink + +#endif // ENABLE(WEB_AUDIO)
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp index b95e4da..492ab00 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
@@ -32,6 +32,10 @@ #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" +#include "modules/webaudio/DeferredTaskHandler.h" +#include "modules/webaudio/OfflineAudioCompletionEvent.h" +#include "modules/webaudio/OfflineAudioDestinationNode.h" + #include "platform/audio/AudioUtilities.h" namespace blink { @@ -76,7 +80,7 @@ return nullptr; } - OfflineAudioContext* audioContext = new OfflineAudioContext(document, numberOfChannels, numberOfFrames, sampleRate); + OfflineAudioContext* audioContext = new OfflineAudioContext(document, numberOfChannels, numberOfFrames, sampleRate, exceptionState); if (!audioContext->destination()) { exceptionState.throwDOMException( @@ -91,19 +95,49 @@ return audioContext; } -OfflineAudioContext::OfflineAudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) +OfflineAudioContext::OfflineAudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) : AbstractAudioContext(document, numberOfChannels, numberOfFrames, sampleRate) + , m_isRenderingStarted(false) + , m_totalRenderFrames(numberOfFrames) { + // Create a new destination for offline rendering. + m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate); + + // Throw an exception if the render target is not ready. + if (m_renderTarget) { + m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get()); + } else { + exceptionState.throwRangeError(ExceptionMessages::failedToConstruct( + "OfflineAudioContext", + "failed to create OfflineAudioContext(" + + String::number(numberOfChannels) + ", " + + String::number(numberOfFrames) + ", " + + String::number(sampleRate) + ")")); + } + + initialize(); } OfflineAudioContext::~OfflineAudioContext() { } +DEFINE_TRACE(OfflineAudioContext) +{ + visitor->trace(m_renderTarget); + visitor->trace(m_completeResolver); + visitor->trace(m_scheduledSuspends); + AbstractAudioContext::trace(visitor); +} + ScriptPromise OfflineAudioContext::startOfflineRendering(ScriptState* scriptState) { + ASSERT(isMainThread()); + // Calling close() on an OfflineAudioContext is not supported/allowed, // but it might well have been stopped by its execution context. + // + // See: crbug.com/435867 if (isContextClosed()) { return ScriptPromise::rejectWithDOMException( scriptState, @@ -112,8 +146,17 @@ "cannot call startRendering on an OfflineAudioContext in a stopped state.")); } - if (m_offlineResolver) { - // Can't call startRendering more than once. Return a rejected promise now. + // If the context is not in the suspended state (i.e. running), reject the promise. + if (contextState() != AudioContextState::Suspended) { + return ScriptPromise::rejectWithDOMException( + scriptState, + DOMException::create( + InvalidStateError, + "cannot startRendering when an OfflineAudioContext is " + state())); + } + + // Can't call startRendering more than once. Return a rejected promise now. + if (m_isRenderingStarted) { return ScriptPromise::rejectWithDOMException( scriptState, DOMException::create( @@ -121,34 +164,235 @@ "cannot call startRendering more than once")); } - m_offlineResolver = ScriptPromiseResolver::create(scriptState); - startRendering(); - return m_offlineResolver->promise(); + ASSERT(!m_isRenderingStarted); + + m_completeResolver = ScriptPromiseResolver::create(scriptState); + + // Start rendering and return the promise. + m_isRenderingStarted = true; + setContextState(Running); + destinationHandler().startRendering(); + + return m_completeResolver->promise(); } ScriptPromise OfflineAudioContext::closeContext(ScriptState* scriptState) { return ScriptPromise::rejectWithDOMException( scriptState, - DOMException::create(InvalidAccessError, "cannot close an OfflineAudioContext.")); + DOMException::create( + InvalidAccessError, + "cannot close an OfflineAudioContext.")); } ScriptPromise OfflineAudioContext::suspendContext(ScriptState* scriptState) { - return ScriptPromise::rejectWithDOMException( - scriptState, - DOMException::create( - InvalidAccessError, - "cannot suspend an OfflineAudioContext")); + // This CANNOT be called on OfflineAudioContext; this is only to implement + // the pure virtual interface from AbstractAudioContext. + RELEASE_ASSERT_NOT_REACHED(); + + return ScriptPromise(); +} + +ScriptPromise OfflineAudioContext::suspendContext(ScriptState* scriptState, double when) +{ + ASSERT(isMainThread()); + + ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + + // The render thread does not exist; reject the promise. + if (!destinationHandler().offlineRenderThread()) { + resolver->reject(DOMException::create(InvalidStateError, + "the rendering is already finished")); + return promise; + } + + // The specified suspend time is negative; reject the promise. + if (when < 0) { + resolver->reject(DOMException::create(InvalidStateError, + "negative suspend time (" + String::number(when) + ") is not allowed")); + return promise; + } + + // Quantize (to the lower boundary) the suspend time by the render quantum. + size_t frame = when * sampleRate(); + frame -= frame % destinationHandler().renderQuantumFrames(); + + // The suspend time should be earlier than the total render frame. If the + // requested suspension time is equal to the total render frame, the promise + // will be rejected. + if (m_totalRenderFrames <= frame) { + resolver->reject(DOMException::create(InvalidStateError, + "cannot schedule a suspend at frame " + String::number(frame) + + " (" + String::number(when) + " seconds) " + + "because it is greater than or equal to the total render duration of " + + String::number(m_totalRenderFrames) + " frames")); + return promise; + } + + // The specified suspend time is in the past; reject the promise. + if (frame < currentSampleFrame()) { + resolver->reject(DOMException::create(InvalidStateError, + "cannot schedule a suspend at frame " + + String::number(frame) + " (" + String::number(when) + + " seconds) because it is earlier than the current frame of " + + String::number(currentSampleFrame()) + " (" + + String::number(currentTime()) + " seconds)")); + return promise; + } + + // Wait until the suspend map is available for the insertion. Here we should + // use AutoLocker because it locks the graph from the main thread. + AutoLocker locker(this); + + // If there is a duplicate suspension at the same quantized frame, + // reject the promise. + if (m_scheduledSuspends.contains(frame)) { + resolver->reject(DOMException::create(InvalidStateError, + "cannot schedule more than one suspend at frame " + + String::number(frame) + " (" + + String::number(when) + " seconds)")); + return promise; + } + + m_scheduledSuspends.add(frame, resolver); + + return promise; } ScriptPromise OfflineAudioContext::resumeContext(ScriptState* scriptState) { - return ScriptPromise::rejectWithDOMException( - scriptState, - DOMException::create( - InvalidAccessError, - "cannot resume an OfflineAudioContext")); + ASSERT(isMainThread()); + + ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + + // If the rendering has not started, reject the promise. + if (!m_isRenderingStarted) { + resolver->reject(DOMException::create(InvalidStateError, + "cannot resume an offline context that has not started")); + return promise; + } + + // If the context is in a closed state, reject the promise. + if (contextState() == AudioContextState::Closed) { + resolver->reject(DOMException::create(InvalidStateError, + "cannot resume a closed offline context")); + return promise; + } + + // If the context is already running, resolve the promise without altering + // the current state or starting the rendering loop. + if (contextState() == AudioContextState::Running) { + resolver->resolve(); + return promise; + } + + ASSERT(contextState() == AudioContextState::Suspended); + + // If the context is suspended, resume rendering by setting the state to + // "Running". and calling startRendering(). Note that resuming is possible + // only after the rendering started. + setContextState(Running); + destinationHandler().startRendering(); + + // Resolve the promise immediately. + resolver->resolve(); + + return promise; +} + +void OfflineAudioContext::fireCompletionEvent() +{ + ASSERT(isMainThread()); + + // We set the state to closed here so that the oncomplete event handler sees + // that the context has been closed. + setContextState(Closed); + + AudioBuffer* renderedBuffer = renderTarget(); + + ASSERT(renderedBuffer); + if (!renderedBuffer) + return; + + // Avoid firing the event if the document has already gone away. + if (executionContext()) { + // Call the offline rendering completion event listener and resolve the + // promise too. + dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); + m_completeResolver->resolve(renderedBuffer); + } else { + // The resolver should be rejected when the execution context is gone. + m_completeResolver->reject(DOMException::create(InvalidStateError, + "the execution context does not exist")); + } +} + +bool OfflineAudioContext::handlePreOfflineRenderTasks() +{ + ASSERT(isAudioThread()); + + // OfflineGraphAutoLocker here locks the audio graph for this scope. Note + // that this locker does not use tryLock() inside because the timing of + // suspension MUST NOT be delayed. + OfflineGraphAutoLocker locker(this); + + deferredTaskHandler().handleDeferredTasks(); + handleStoppableSourceNodes(); + + return shouldSuspend(); +} + +void OfflineAudioContext::handlePostOfflineRenderTasks() +{ + ASSERT(isAudioThread()); + + // OfflineGraphAutoLocker here locks the audio graph for the same reason + // above in |handlePreOfflineRenderTasks|. + OfflineGraphAutoLocker locker(this); + + deferredTaskHandler().breakConnections(); + releaseFinishedSourceNodes(); + deferredTaskHandler().handleDeferredTasks(); + deferredTaskHandler().requestToDeleteHandlersOnMainThread(); +} + + +OfflineAudioDestinationHandler& OfflineAudioContext::destinationHandler() +{ + return static_cast<OfflineAudioDestinationHandler&>(destination()->audioDestinationHandler()); +} + +void OfflineAudioContext::resolveSuspendOnMainThread(size_t frame) +{ + ASSERT(isMainThread()); + + // Suspend the context first. This will fire onstatechange event. + setContextState(Suspended); + + // Wait until the suspend map is available for the removal. + AutoLocker locker(this); + + ASSERT(m_scheduledSuspends.contains(frame)); + + SuspendMap::iterator it = m_scheduledSuspends.find(frame); + it->value->resolve(); + + m_scheduledSuspends.remove(it); +} + +bool OfflineAudioContext::shouldSuspend() +{ + ASSERT(isAudioThread()); + + // Note that the GraphLock is required before this check. Since this needs + // to run on the audio thread, OfflineGraphAutoLocker must be used. + if (m_scheduledSuspends.contains(currentSampleFrame())) + return true; + + return false; } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h index 030586f..85d99d75 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
@@ -27,10 +27,12 @@ #include "modules/ModulesExport.h" #include "modules/webaudio/AbstractAudioContext.h" +#include "wtf/HashMap.h" namespace blink { class ExceptionState; +class OfflineAudioDestinationHandler; class MODULES_EXPORT OfflineAudioContext final : public AbstractAudioContext { DEFINE_WRAPPERTYPEINFO(); @@ -39,16 +41,76 @@ ~OfflineAudioContext() override; + DECLARE_VIRTUAL_TRACE(); + ScriptPromise startOfflineRendering(ScriptState*); ScriptPromise closeContext(ScriptState*) final; - ScriptPromise suspendContext(ScriptState*) final; + ScriptPromise suspendContext(ScriptState*, double); ScriptPromise resumeContext(ScriptState*) final; + // This is to implement the pure virtual method from AbstractAudioContext. + // CANNOT be called from an OfflineAudioContext. + ScriptPromise suspendContext(ScriptState*) final; + bool hasRealtimeConstraint() final { return false; } + DEFINE_ATTRIBUTE_EVENT_LISTENER(complete); + + // Fire completion event when the rendering is finished. + void fireCompletionEvent(); + + // This is same with the online version in AbstractAudioContext class except + // for returning a boolean value after checking the scheduled suspends. + bool handlePreOfflineRenderTasks(); + + void handlePostOfflineRenderTasks(); + + // Resolve a suspend scheduled at the specified frame. With this specified + // frame as a unique key, the associated promise resolver can be retrieved + // from the map (m_scheduledSuspends) and resolved. + void resolveSuspendOnMainThread(size_t); + + // The HashMap with 'zero' key is needed because |currentSampleFrame| can be + // zero. + using SuspendMap = HeapHashMap<size_t, Member<ScriptPromiseResolver>, DefaultHash<size_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<size_t>>; + + using OfflineGraphAutoLocker = DeferredTaskHandler::OfflineGraphAutoLocker; + private: - OfflineAudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); + OfflineAudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState&); + + // Fetch directly the destination handler. + OfflineAudioDestinationHandler& destinationHandler(); + + AudioBuffer* renderTarget() const { return m_renderTarget.get(); } + + // Check if the rendering needs to be suspended. + bool shouldSuspend(); + + Member<AudioBuffer> m_renderTarget; + + // This map is to store the timing of scheduled suspends (frame) and the + // associated promise resolver. This storage can only be modified by the + // main thread and accessed by the audio thread with the graph lock. + // + // The map consists of key-value pairs of: + // { size_t quantizedFrame: ScriptPromiseResolver resolver } + // + // Note that |quantizedFrame| is a unique key, since you can have only one + // suspend scheduled for a certain frame. Accessing to this must be + // protected by the offline context lock. + SuspendMap m_scheduledSuspends; + + Member<ScriptPromiseResolver> m_completeResolver; + + // This flag is necessary to indicate the rendering has actually started. + // Note that initial state of context is 'Suspended', which is the same + // state when the context is suspended. + bool m_isRenderingStarted; + + // Total render sample length. + size_t m_totalRenderFrames; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl index 4c225d938..0b12e30 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl
@@ -31,5 +31,7 @@ ] interface OfflineAudioContext : AudioContext { // Offline rendering attribute EventHandler oncomplete; - [CallWith=ScriptState,ImplementedAs=startOfflineRendering] Promise<AudioBuffer> startRendering(); + [CallWith=ScriptState, ImplementedAs=startOfflineRendering, MeasureAs=OfflineAudioContextStartRendering] Promise<AudioBuffer> startRendering(); + [CallWith=ScriptState, ImplementedAs=suspendContext, MeasureAs=OfflineAudioContextSuspend] Promise<void> suspend(double suspendTime); + [CallWith=ScriptState, ImplementedAs=resumeContext, MeasureAs=OfflineAudioContextResume] Promise<void> resume(); };
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp index 21be406..a21f7a5 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
@@ -28,22 +28,31 @@ #include "core/dom/CrossThreadTask.h" #include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/AudioNodeInput.h" +#include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/OfflineAudioContext.h" #include "platform/Task.h" #include "platform/audio/AudioBus.h" +#include "platform/audio/DenormalDisabler.h" #include "platform/audio/HRTFDatabaseLoader.h" #include "public/platform/Platform.h" #include <algorithm> namespace blink { -const size_t renderQuantumSize = 128; +const size_t OfflineAudioDestinationHandler::renderQuantumSize = 128; OfflineAudioDestinationHandler::OfflineAudioDestinationHandler(AudioNode& node, AudioBuffer* renderTarget) : AudioDestinationHandler(node, renderTarget->sampleRate()) , m_renderTarget(renderTarget) - , m_startedRendering(false) + , m_renderThread(adoptPtr(Platform::current()->createThread("offline audio renderer"))) + , m_framesProcessed(0) + , m_framesToProcess(0) + , m_isRenderingStarted(false) + , m_shouldSuspend(false) { m_renderBus = AudioBus::create(renderTarget->numberOfChannels(), renderQuantumSize); + m_framesToProcess = m_renderTarget->length(); } PassRefPtr<OfflineAudioDestinationHandler> OfflineAudioDestinationHandler::create(AudioNode& node, AudioBuffer* renderTarget) @@ -81,34 +90,51 @@ AudioHandler::uninitialize(); } +OfflineAudioContext* OfflineAudioDestinationHandler::context() const +{ + return static_cast<OfflineAudioContext*>(m_context); +} + void OfflineAudioDestinationHandler::startRendering() { ASSERT(isMainThread()); + ASSERT(m_renderThread); ASSERT(m_renderTarget); + if (!m_renderTarget) return; - if (!m_startedRendering) { - m_startedRendering = true; - m_renderThread = adoptPtr(Platform::current()->createThread("Offline Audio Renderer")); - m_renderThread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSafeBind(&OfflineAudioDestinationHandler::offlineRender, PassRefPtr<OfflineAudioDestinationHandler>(this)))); + // Rendering was not started. Starting now. + if (!m_isRenderingStarted) { + m_isRenderingStarted = true; + m_renderThread->taskRunner()->postTask(BLINK_FROM_HERE, + new Task(threadSafeBind(&OfflineAudioDestinationHandler::startOfflineRendering, this))); + return; } + + // Rendering is already started, which implicitly means we resume the + // rendering by calling |doOfflineRendering| on the render thread. + m_renderThread->taskRunner()->postTask(BLINK_FROM_HERE, + threadSafeBind(&OfflineAudioDestinationHandler::doOfflineRendering, this)); } void OfflineAudioDestinationHandler::stopRendering() { + // offline audio rendering CANNOT BE stopped by JavaScript. ASSERT_NOT_REACHED(); } -void OfflineAudioDestinationHandler::offlineRender() +WebThread* OfflineAudioDestinationHandler::offlineRenderThread() { - offlineRenderInternal(); - context()->handlePostRenderTasks(); + ASSERT(m_renderThread); + + return m_renderThread.get(); } -void OfflineAudioDestinationHandler::offlineRenderInternal() +void OfflineAudioDestinationHandler::startOfflineRendering() { ASSERT(!isMainThread()); + ASSERT(m_renderBus); if (!m_renderBus) return; @@ -128,40 +154,141 @@ if (!isRenderBusAllocated) return; - // Break up the render target into smaller "render quantize" sized pieces. - // Render until we're finished. - size_t framesToProcess = m_renderTarget->length(); + // Start rendering. + doOfflineRendering(); +} + +void OfflineAudioDestinationHandler::doOfflineRendering() +{ + ASSERT(!isMainThread()); + unsigned numberOfChannels = m_renderTarget->numberOfChannels(); - unsigned n = 0; - while (framesToProcess > 0) { - // Render one render quantum. - render(0, m_renderBus.get(), renderQuantumSize); + // Reset the suspend flag. + m_shouldSuspend = false; - size_t framesAvailableToCopy = std::min(framesToProcess, renderQuantumSize); + // If there is more to process and there is no suspension at the moment, + // do continue to render quanta. Then calling OfflineAudioContext.resume() will pick up + // the render loop again from where it was suspended. + while (m_framesToProcess > 0 && !m_shouldSuspend) { + + // Suspend the rendering and update m_shouldSuspend if a scheduled + // suspend found at the current sample frame. Otherwise render one + // quantum and return false. + m_shouldSuspend = renderIfNotSuspended(0, m_renderBus.get(), renderQuantumSize); + + if (m_shouldSuspend) + return; + + size_t framesAvailableToCopy = std::min(m_framesToProcess, renderQuantumSize); for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { const float* source = m_renderBus->channel(channelIndex)->data(); float* destination = m_renderTarget->getChannelData(channelIndex)->data(); - memcpy(destination + n, source, sizeof(float) * framesAvailableToCopy); + memcpy(destination + m_framesProcessed, source, sizeof(float) * framesAvailableToCopy); } - n += framesAvailableToCopy; - framesToProcess -= framesAvailableToCopy; + m_framesProcessed += framesAvailableToCopy; + + ASSERT(m_framesToProcess >= framesAvailableToCopy); + m_framesToProcess -= framesAvailableToCopy; } - // Our work is done. Let the AbstractAudioContext know. - if (context()->executionContext()) - context()->executionContext()->postTask(BLINK_FROM_HERE, createCrossThreadTask(&OfflineAudioDestinationHandler::notifyComplete, PassRefPtr<OfflineAudioDestinationHandler>(this))); + // Finish up the rendering loop if there is no more to process. + if (!m_framesToProcess) + finishOfflineRendering(); +} + +void OfflineAudioDestinationHandler::suspendOfflineRendering() +{ + ASSERT(!isMainThread()); + + // The actual rendering has been suspended. Notify the context. + if (context()->executionContext()) { + context()->executionContext()->postTask(BLINK_FROM_HERE, + createCrossThreadTask(&OfflineAudioDestinationHandler::notifySuspend, this)); + } +} + +void OfflineAudioDestinationHandler::finishOfflineRendering() +{ + ASSERT(!isMainThread()); + + // The actual rendering has been completed. Notify the context. + if (context()->executionContext()) { + context()->executionContext()->postTask(BLINK_FROM_HERE, + createCrossThreadTask(&OfflineAudioDestinationHandler::notifyComplete, this)); + } +} + +void OfflineAudioDestinationHandler::notifySuspend() +{ + if (context()) + context()->resolveSuspendOnMainThread(context()->currentSampleFrame()); } void OfflineAudioDestinationHandler::notifyComplete() { - // The AbstractAudioContext might be gone. + // The OfflineAudioContext might be gone. if (context()) context()->fireCompletionEvent(); } +bool OfflineAudioDestinationHandler::renderIfNotSuspended(AudioBus* sourceBus, AudioBus* destinationBus, size_t numberOfFrames) +{ + // We don't want denormals slowing down any of the audio processing + // since they can very seriously hurt performance. + // This will take care of all AudioNodes because they all process within this scope. + DenormalDisabler denormalDisabler; + + context()->deferredTaskHandler().setAudioThread(currentThread()); + + if (!context()->isDestinationInitialized()) { + destinationBus->zero(); + return false; + } + + // Take care pre-render tasks at the beginning of each render quantum. Then + // it will stop the rendering loop if the context needs to be suspended + // at the beginning of the next render quantum. + if (context()->handlePreOfflineRenderTasks()) { + suspendOfflineRendering(); + return true; + } + + // Prepare the local audio input provider for this render quantum. + if (sourceBus) + m_localAudioInputProvider.set(sourceBus); + + ASSERT(numberOfInputs() >= 1); + if (numberOfInputs() < 1) { + destinationBus->zero(); + return false; + } + // This will cause the node(s) connected to us to process, which in turn will pull on their input(s), + // all the way backwards through the rendering graph. + AudioBus* renderedBus = input(0).pull(destinationBus, numberOfFrames); + + if (!renderedBus) { + destinationBus->zero(); + } else if (renderedBus != destinationBus) { + // in-place processing was not possible - so copy + destinationBus->copyFrom(*renderedBus); + } + + // Process nodes which need a little extra help because they are not connected to anything, but still need to process. + context()->deferredTaskHandler().processAutomaticPullNodes(numberOfFrames); + + // Let the context take care of any business at the end of each render quantum. + context()->handlePostOfflineRenderTasks(); + + // Advance current sample-frame. + size_t newSampleFrame = m_currentSampleFrame + numberOfFrames; + releaseStore(&m_currentSampleFrame, newSampleFrame); + + return false; +} + // ---------------------------------------------------------------- OfflineAudioDestinationNode::OfflineAudioDestinationNode(AbstractAudioContext& context, AudioBuffer* renderTarget)
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h index 73681041..b900a92 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h
@@ -27,6 +27,7 @@ #include "modules/webaudio/AudioBuffer.h" #include "modules/webaudio/AudioDestinationNode.h" +#include "modules/webaudio/OfflineAudioContext.h" #include "public/platform/WebThread.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -35,6 +36,7 @@ class AbstractAudioContext; class AudioBus; +class OfflineAudioContext; class OfflineAudioDestinationHandler final : public AudioDestinationHandler { public: @@ -46,20 +48,47 @@ void initialize() override; void uninitialize() override; + OfflineAudioContext* context() const final; + // AudioDestinationHandler void startRendering() override; void stopRendering() override; float sampleRate() const override { return m_renderTarget->sampleRate(); } + size_t renderQuantumFrames() const { return renderQuantumSize; } + + WebThread* offlineRenderThread(); + private: OfflineAudioDestinationHandler(AudioNode&, AudioBuffer* renderTarget); - void offlineRender(); - void offlineRenderInternal(); - // For completion callback on main thread. + static const size_t renderQuantumSize; + + // Set up the rendering and start. After setting the context up, it will + // eventually call |doOfflineRendering|. + void startOfflineRendering(); + + // Suspend the rendering loop and notify the main thread to resolve the + // associated promise. + void suspendOfflineRendering(); + + // Start the rendering loop. + void doOfflineRendering(); + + // Finish the rendering loop and notify the main thread to resolve the + // promise with the rendered buffer. + void finishOfflineRendering(); + + // Suspend/completion callbacks for the main thread. + void notifySuspend(); void notifyComplete(); + // The offline version of render() method. If the rendering needs to be + // suspended after checking, this stops the rendering and returns true. + // Otherwise, it returns false after rendering one quantum. + bool renderIfNotSuspended(AudioBus* sourceBus, AudioBus* destinationBus, size_t numberOfFrames); + // This AudioHandler renders into this AudioBuffer. // This Persistent doesn't make a reference cycle including the owner // OfflineAudioDestinationNode. @@ -69,7 +98,19 @@ // Rendering thread. OwnPtr<WebThread> m_renderThread; - bool m_startedRendering; + + // These variables are for counting the number of frames for the current + // progress and the remaining frames to be processed. + size_t m_framesProcessed; + size_t m_framesToProcess; + + // This flag is necessary to distinguish the state of the context between + // 'created' and 'suspended'. If this flag is false and the current state + // is 'suspended', it means the context is created and have not started yet. + bool m_isRenderingStarted; + + // This flag indicates whether the rendering should be suspended or not. + bool m_shouldSuspend; }; class OfflineAudioDestinationNode final : public AudioDestinationNode {
diff --git a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp index 3bd3ca6..425193a 100644 --- a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "config.h" +#if ENABLE(WEB_AUDIO) #include "modules/webaudio/ScriptProcessorNode.h" #include "core/testing/DummyPageHolder.h" @@ -28,3 +29,5 @@ } } // namespace blink + +#endif // ENABLE(WEB_AUDIO)
diff --git a/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp index 4c8b72e..dbe23a1 100644 --- a/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "config.h" +#if ENABLE(WEB_AUDIO) #include "modules/webaudio/StereoPannerNode.h" #include "core/testing/DummyPageHolder.h" @@ -26,3 +27,5 @@ } } // namespace blink + +#endif // ENABLE(WEB_AUDIO)
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp index daff13f..c743328 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -94,6 +94,9 @@ GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8, +}; + +const GLenum kCompressedTextureFormatsETC2EAC[] = { GL_COMPRESSED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_RG11_EAC, @@ -110,6 +113,8 @@ : WebGLRenderingContextBase(passedCanvas, context, requestedAttributes) { m_supportedInternalFormatsStorage.insert(kSupportedInternalFormatsStorage, kSupportedInternalFormatsStorage + arraysize(kSupportedInternalFormatsStorage)); + m_supportedInternalFormatsStorage.insert(kCompressedTextureFormatsETC2EAC, kCompressedTextureFormatsETC2EAC + arraysize(kCompressedTextureFormatsETC2EAC)); + m_compressedTextureFormatsETC2EAC.insert(kCompressedTextureFormatsETC2EAC, kCompressedTextureFormatsETC2EAC + arraysize(kCompressedTextureFormatsETC2EAC)); } WebGL2RenderingContextBase::~WebGL2RenderingContextBase() @@ -697,6 +702,11 @@ if (!tex) return false; + if (functionType == TexStorageType3D && target != GL_TEXTURE_2D_ARRAY && m_compressedTextureFormatsETC2EAC.find(internalformat) != m_compressedTextureFormatsETC2EAC.end()) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "target for ETC2/EAC internal formats must be TEXTURE_2D_ARRAY"); + return false; + } + if (m_supportedInternalFormatsStorage.find(internalformat) == m_supportedInternalFormatsStorage.end()) { synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid internalformat"); return false;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h index 726ceb2..0488e54 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h
@@ -239,6 +239,7 @@ GLint m_maxArrayTextureLayers; std::set<GLenum> m_supportedInternalFormatsStorage; + std::set<GLenum> m_compressedTextureFormatsETC2EAC; PersistentWillBeMember<WebGLBuffer> m_boundCopyReadBuffer; PersistentWillBeMember<WebGLBuffer> m_boundCopyWriteBuffer;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp b/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp index 8702f13..11de4927 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.cpp
@@ -72,7 +72,7 @@ const GLenum* bufs = buffers.data(); if (!scoped.context()->m_framebufferBinding) { if (n != 1) { - scoped.context()->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than one buffer"); + scoped.context()->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "must provide exactly one buffer"); return; } if (bufs[0] != GL_BACK && bufs[0] != GL_NONE) {
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp index 348c02d..68cc4c7 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
@@ -50,6 +50,7 @@ GLsizei height() const override; GLenum format() const override; GLenum type() const override; + bool isCubeComplete() const override; WebGLSharedObject* object() const override; bool isSharedObject(WebGLSharedObject*) const override; bool valid() const override; @@ -143,6 +144,12 @@ return WebGLTexture::getValidTypeForInternalFormat(m_renderbuffer->internalFormat()); } +bool WebGLRenderbufferAttachment::isCubeComplete() const +{ + ASSERT_NOT_REACHED(); + return false; +} + class WebGLTextureAttachment final : public WebGLFramebuffer::WebGLAttachment { public: static WebGLFramebuffer::WebGLAttachment* create(WebGLTexture*, GLenum target, GLint level, GLint layer); @@ -157,6 +164,7 @@ GLsizei height() const override; GLenum format() const override; GLenum type() const override; + bool isCubeComplete() const override; WebGLSharedObject* object() const override; bool isSharedObject(WebGLSharedObject*) const override; bool valid() const override; @@ -254,6 +262,11 @@ return m_texture->getType(m_target, m_level); } +bool WebGLTextureAttachment::isCubeComplete() const +{ + return m_texture->isCubeComplete(); +} + bool isColorRenderable(GLenum internalformat, bool includesFloat) { switch (internalformat) { @@ -450,6 +463,12 @@ *reason = "attachment has a 0 dimension"; return false; } + + if (attachedObject->object()->isTexture() && !attachedObject->isCubeComplete()) { + *reason = "attachment is not cube complete"; + return false; + } + return true; }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h index 6522650..1b61c5d4 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h
@@ -49,6 +49,7 @@ // To avoid confusion, it would be better to not implement type() for renderbuffer attachment and // we should always use the internalformat of the renderbuffer and avoid using type() API. virtual GLenum type() const = 0; + virtual bool isCubeComplete() const = 0; virtual WebGLSharedObject* object() const = 0; virtual bool isSharedObject(WebGLSharedObject*) const = 0; virtual bool valid() const = 0;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLTexture.h b/third_party/WebKit/Source/modules/webgl/WebGLTexture.h index c8c3524..8c0b749f 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLTexture.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLTexture.h
@@ -68,6 +68,8 @@ static GLenum getValidFormatForInternalFormat(GLenum); + bool isCubeComplete() const { return m_isCubeComplete; } + // Whether width/height is NotPowerOfTwo. static bool isNPOT(GLsizei, GLsizei);
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp index 0a61dcf..f68c767 100644 --- a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp +++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
@@ -234,9 +234,7 @@ DOMWebSocket::~DOMWebSocket() { - WebSocketChannel* channel = m_channel; - // TODO(yhirano): Use ASSERT instead when crbug.com/550632 is fixed. - RELEASE_ASSERT(!channel); + ASSERT(!m_channel); } void DOMWebSocket::logError(const String& message) @@ -573,8 +571,7 @@ void DOMWebSocket::contextDestroyed() { WTF_LOG(Network, "WebSocket %p contextDestroyed()", this); - // TODO(yhirano): Use ASSERT instead when crbug.com/550632 is fixed. - RELEASE_ASSERT(!m_channel); + ASSERT(!m_channel); ASSERT(m_state == CLOSED); ActiveDOMObject::contextDestroyed(); }
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp index bab7a96..684d076 100644 --- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp +++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
@@ -388,11 +388,6 @@ return toDocument(context); } -void DocumentWebSocketChannel::handleShouldBeDisconnected() -{ - RELEASE_ASSERT(!m_handle); -} - void DocumentWebSocketChannel::didConnect(WebSocketHandle* handle, const WebString& selectedProtocol, const WebString& extensions) { WTF_LOG(Network, "DocumentWebSocketChannel %p didConnect(%p, %s, %s)", this, handle, selectedProtocol.utf8().c_str(), extensions.utf8().c_str());
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h index 62d8fe9..5f1bb6c 100644 --- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h +++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h
@@ -62,7 +62,6 @@ // DOMWindow (i.e. works in the main thread). class MODULES_EXPORT DocumentWebSocketChannel final : public WebSocketChannel, public WebSocketHandleClient, public ContextLifecycleObserver { WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DocumentWebSocketChannel); - USING_PRE_FINALIZER(DocumentWebSocketChannel, handleShouldBeDisconnected); public: // You can specify the source file and the line number information // explicitly by passing the last parameter. @@ -134,7 +133,6 @@ void abortAsyncOperations(); void handleDidClose(bool wasClean, unsigned short code, const String& reason); Document* document(); - void handleShouldBeDisconnected(); // WebSocketHandleClient functions. void didConnect(WebSocketHandle*, const WebString& selectedProtocol, const WebString& extensions) override;
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp index 16e026d..8da3121 100644 --- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp +++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
@@ -476,11 +476,6 @@ return !m_workerGlobalScope->thread()->terminated(); } -void Bridge::peerShouldBeDisconnected() -{ - RELEASE_ASSERT(!m_peer); -} - DEFINE_TRACE(Bridge) { visitor->trace(m_client);
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h index 15ff20f..a14a36df 100644 --- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h +++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
@@ -123,7 +123,6 @@ // Bridge for Peer. Running on the worker thread. class Bridge final : public GarbageCollectedFinalized<Bridge> { WTF_MAKE_NONCOPYABLE(Bridge); - USING_PRE_FINALIZER(Bridge, peerShouldBeDisconnected); public: Bridge(WebSocketChannelClient*, WorkerGlobalScope&); ~Bridge(); @@ -146,7 +145,6 @@ private: // Returns false if shutdown event is received before method completion. bool waitForMethodCompletion(PassOwnPtr<ExecutionContextTask>); - void peerShouldBeDisconnected(); Member<WebSocketChannelClient> m_client; RefPtrWillBeMember<WorkerGlobalScope> m_workerGlobalScope;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index a7158d1..2bc8c089 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -196,6 +196,8 @@ ] public_deps = [ + "//base", + "//cc", "//gpu/command_buffer/client:gles2_c_lib", "//skia", "//third_party:jpeg", @@ -213,6 +215,7 @@ "//third_party/WebKit/Source/wtf", "//third_party/harfbuzz-ng", "//third_party/icu", + "//ui/gfx/geometry", ] if (is_mac) {
diff --git a/third_party/WebKit/Source/platform/DEPS b/third_party/WebKit/Source/platform/DEPS index 99c3cc6f..64e0caef8 100644 --- a/third_party/WebKit/Source/platform/DEPS +++ b/third_party/WebKit/Source/platform/DEPS
@@ -1,10 +1,13 @@ include_rules = [ + "+base/memory", + "+base/trace_event", "+mozilla", "+platform", "+public/platform", "+skia/ext", "+third_party/khronos", "+third_party/skia", + "+ui/gfx/geometry", "+url", "+webp", "-bindings",
diff --git a/third_party/WebKit/Source/platform/MemoryPurgeController.cpp b/third_party/WebKit/Source/platform/MemoryPurgeController.cpp index 2f70de2..d00d9cc 100644 --- a/third_party/WebKit/Source/platform/MemoryPurgeController.cpp +++ b/third_party/WebKit/Source/platform/MemoryPurgeController.cpp
@@ -45,7 +45,17 @@ void MemoryPurgeController::pageInactiveTask(Timer<MemoryPurgeController>*) { + static const size_t maxSizeInKB = 10 * 1024; + + size_t totalSizeBefore = WTF::Partitions::totalSizeOfCommittedPages(); purgeMemory(MemoryPurgeMode::InactiveTab); + size_t totalSizeAfter = WTF::Partitions::totalSizeOfCommittedPages(); + if (totalSizeAfter >= totalSizeBefore) + return; + size_t reclaimedInKB = (totalSizeBefore - totalSizeAfter) / 1024 + 1; + if (reclaimedInKB >= maxSizeInKB) + reclaimedInKB = maxSizeInKB - 1; + Platform::current()->histogramCustomCounts("MemoryPurgeController.ReclaimedPartitionAllocInactiveTab", reclaimedInKB, 1, maxSizeInKB, 50); } void MemoryPurgeController::purgeMemory(MemoryPurgeMode purgeMode)
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index 05abb9b..c0ddbc0 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -44,6 +44,7 @@ CSSAttributeCaseSensitivity status=experimental CSSBackdropFilter status=experimental CSSCompositing status=stable +CSSFontDisplay status=experimental CSSFontSizeAdjust status=experimental CSSGridLayout status=experimental CSSIndependentTransformProperties status=experimental
diff --git a/third_party/WebKit/Source/platform/blink_platform.gyp b/third_party/WebKit/Source/platform/blink_platform.gyp index 701bded1d..41f591e 100644 --- a/third_party/WebKit/Source/platform/blink_platform.gyp +++ b/third_party/WebKit/Source/platform/blink_platform.gyp
@@ -182,21 +182,26 @@ 'blink_common', 'blink_heap_asm_stubs', 'blink_prerequisites', + 'platform_generated.gyp:make_platform_generated', + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/cc/cc.gyp:cc', '<(DEPTH)/gpu/gpu.gyp:gles2_c_lib', '<(DEPTH)/skia/skia.gyp:skia', + '<(DEPTH)/third_party/iccjpeg/iccjpeg.gyp:iccjpeg', '<(DEPTH)/third_party/icu/icu.gyp:icui18n', '<(DEPTH)/third_party/icu/icu.gyp:icuuc', '<(DEPTH)/third_party/libpng/libpng.gyp:libpng', '<(DEPTH)/third_party/libwebp/libwebp.gyp:libwebp', '<(DEPTH)/third_party/ots/ots.gyp:ots', '<(DEPTH)/third_party/qcms/qcms.gyp:qcms', + '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry', '<(DEPTH)/url/url.gyp:url_lib', '<(DEPTH)/v8/tools/gyp/v8.gyp:v8', - 'platform_generated.gyp:make_platform_generated', - '<(DEPTH)/third_party/iccjpeg/iccjpeg.gyp:iccjpeg', '<(libjpeg_gyp_path):libjpeg', ], 'export_dependent_settings': [ + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/cc/cc.gyp:cc', '<(DEPTH)/gpu/gpu.gyp:gles2_c_lib', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/third_party/libpng/libpng.gyp:libpng',
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp index ebbcafa..b9ce0de3 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -27,10 +27,6 @@ #include "platform/graphics/Canvas2DLayerBridge.h" -#include "GrContext.h" -#include "SkDevice.h" -#include "SkSurface.h" - #include "platform/TraceEvent.h" #include "platform/graphics/CanvasMetrics.h" #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" @@ -44,6 +40,7 @@ #include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/gpu/GrContext.h" #include "wtf/RefCountedLeakCounter.h" namespace {
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp index 9e5c474..47d489c 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -34,7 +34,7 @@ #include "public/platform/WebThread.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkDevice.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/gl/SkNullGLContext.h" #include "wtf/RefPtr.h"
diff --git a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp index 17f7d98..07db366 100644 --- a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp +++ b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
@@ -41,6 +41,7 @@ #include "public/platform/WebRect.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPicture.h" +#include "ui/gfx/geometry/rect.h" namespace blink { @@ -81,6 +82,12 @@ artifact.appendToWebDisplayItemList(list); } +gfx::Rect ContentLayerDelegate::paintableRegion() +{ + IntRect interestRect = m_painter->interestRect(); + return gfx::Rect(interestRect.x(), interestRect.y(), interestRect.width(), interestRect.height()); +} + void ContentLayerDelegate::paintContents( WebDisplayItemList* webDisplayItemList, const WebRect& clip, WebContentLayerClient::PaintingControlSetting paintingControl)
diff --git a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h index e07ce0d..16a681a 100644 --- a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h +++ b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.h
@@ -33,6 +33,10 @@ class SkCanvas; +namespace gfx { +class Rect; +} + namespace blink { class GraphicsContext; @@ -41,6 +45,7 @@ class PLATFORM_EXPORT GraphicsContextPainter { public: + virtual IntRect interestRect() = 0; virtual void paint(GraphicsContext&, const IntRect* interestRect) = 0; virtual PaintController* paintController() = 0; @@ -55,6 +60,8 @@ explicit ContentLayerDelegate(GraphicsContextPainter*); ~ContentLayerDelegate() override; + gfx::Rect paintableRegion() override; + // WebContentLayerClient implementation. void paintContents(WebDisplayItemList*, const WebRect& clip, WebContentLayerClient::PaintingControlSetting = PaintDefaultBehavior) override; size_t approximateUnsharedMemoryUsage() const override;
diff --git a/third_party/WebKit/Source/platform/graphics/DEPS b/third_party/WebKit/Source/platform/graphics/DEPS new file mode 100644 index 0000000..8d825ff2 --- /dev/null +++ b/third_party/WebKit/Source/platform/graphics/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+cc", + "-cc/blink", +]
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp index 7a664ab..e3dcf99 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -28,7 +28,10 @@ #include "SkImageFilter.h" #include "SkMatrix44.h" +#include "base/trace_event/trace_event_argument.h" +#include "cc/layers/layer.h" #include "platform/DragImage.h" +#include "platform/JSONValues.h" #include "platform/TraceEvent.h" #include "platform/geometry/FloatRect.h" #include "platform/geometry/LayoutRect.h" @@ -49,13 +52,13 @@ #include "public/platform/WebFilterOperations.h" #include "public/platform/WebFloatPoint.h" #include "public/platform/WebFloatRect.h" -#include "public/platform/WebGraphicsLayerDebugInfo.h" #include "public/platform/WebLayer.h" #include "public/platform/WebPoint.h" #include "public/platform/WebSize.h" #include "wtf/CurrentTime.h" #include "wtf/HashMap.h" #include "wtf/HashSet.h" +#include "wtf/text/StringUTF8Adaptor.h" #include "wtf/text/WTFString.h" #include <algorithm> @@ -124,7 +127,7 @@ m_contentLayerDelegate = adoptPtr(new ContentLayerDelegate(this)); m_layer = adoptPtr(Platform::current()->compositorSupport()->createContentLayer(m_contentLayerDelegate.get())); m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible); - m_layer->layer()->setWebLayerClient(this); + m_layer->layer()->setLayerClient(this); // TODO(rbyers): Expose control over this to the web - crbug.com/489802: setScrollBlocksOn(WebScrollBlocksOnStartTouch | WebScrollBlocksOnWheelEvent); @@ -292,6 +295,13 @@ setNeedsDisplay(); } +IntRect GraphicsLayer::interestRect() +{ + if (!RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) + m_previousInterestRect = m_client->computeInterestRect(this, m_previousInterestRect); + return m_previousInterestRect; +} + void GraphicsLayer::paint(GraphicsContext& context, const IntRect* interestRect) { ASSERT(interestRect || RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()); @@ -324,9 +334,9 @@ } } + m_previousInterestRect = *interestRect; m_client->paintContents(this, context, m_paintingPhase, *interestRect); notifyFirstPaintToClient(); - m_previousInterestRect = *interestRect; } void GraphicsLayer::notifyFirstPaintToClient() @@ -454,7 +464,7 @@ m_contentsLayer = contentsLayer; m_contentsLayerId = m_contentsLayer->id(); - m_contentsLayer->setWebLayerClient(this); + m_contentsLayer->setLayerClient(this); m_contentsLayer->setTransformOrigin(FloatPoint3D()); m_contentsLayer->setUseParentBackfaceVisibility(true); @@ -485,13 +495,6 @@ return m_debugInfo; } -WebGraphicsLayerDebugInfo* GraphicsLayer::takeDebugInfoFor(WebLayer* layer) -{ - GraphicsLayerDebugInfo* clone = m_debugInfo.clone(); - clone->setDebugName(debugName(layer)); - return clone; -} - WebLayer* GraphicsLayer::contentsLayerIfRegistered() { clearContentsLayerIfUnregistered(); @@ -771,7 +774,12 @@ return json->toPrettyJSONString(); } -String GraphicsLayer::debugName(WebLayer* webLayer) const +static const cc::Layer* ccLayerForWebLayer(const WebLayer* webLayer) +{ + return webLayer ? webLayer->ccLayer() : nullptr; +} + +String GraphicsLayer::debugName(cc::Layer* layer) const { String name; if (!m_client) @@ -779,17 +787,17 @@ String highlightDebugName; for (size_t i = 0; i < m_linkHighlights.size(); ++i) { - if (webLayer == m_linkHighlights[i]->layer()) { + if (layer == ccLayerForWebLayer(m_linkHighlights[i]->layer())) { highlightDebugName = "LinkHighlight[" + String::number(i) + "] for " + m_client->debugName(this); break; } } - if (webLayer == m_contentsLayer) { + if (layer->id() == m_contentsLayerId) { name = "ContentsLayer for " + m_client->debugName(this); } else if (!highlightDebugName.isEmpty()) { name = highlightDebugName; - } else if (webLayer == m_layer->layer()) { + } else if (layer == ccLayerForWebLayer(m_layer->layer())) { name = m_client->debugName(this); } else { ASSERT_NOT_REACHED(); @@ -1143,7 +1151,7 @@ { ASSERT(linkHighlight && !m_linkHighlights.contains(linkHighlight)); m_linkHighlights.append(linkHighlight); - linkHighlight->layer()->setWebLayerClient(this); + linkHighlight->layer()->setLayerClient(this); updateChildList(); } @@ -1191,6 +1199,13 @@ } } +scoped_refptr<base::trace_event::ConvertableToTraceFormat> GraphicsLayer::TakeDebugInfo(cc::Layer* layer) +{ + scoped_refptr<base::trace_event::TracedValue> tracedValue = m_debugInfo.asTracedValue(); + tracedValue->SetString("layer_name", WTF::StringUTF8Adaptor(debugName(layer)).asStringPiece()); + return tracedValue; +} + PaintController* GraphicsLayer::paintController() { if (!m_paintController)
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h index 6e58663..de584cc 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -27,6 +27,7 @@ #ifndef GraphicsLayer_h #define GraphicsLayer_h +#include "cc/layers/layer_client.h" #include "platform/PlatformExport.h" #include "platform/geometry/FloatPoint.h" #include "platform/geometry/FloatPoint3D.h" @@ -47,7 +48,6 @@ #include "public/platform/WebCompositorAnimationDelegate.h" #include "public/platform/WebContentLayer.h" #include "public/platform/WebImageLayer.h" -#include "public/platform/WebLayerClient.h" #include "public/platform/WebLayerScrollClient.h" #include "public/platform/WebScrollBlocksOn.h" #include "third_party/skia/include/core/SkPaint.h" @@ -75,7 +75,7 @@ // GraphicsLayer is an abstraction for a rendering surface with backing store, // which may have associated transformation and animations. -class PLATFORM_EXPORT GraphicsLayer : public GraphicsContextPainter, public WebCompositorAnimationDelegate, public WebLayerScrollClient, public WebLayerClient { +class PLATFORM_EXPORT GraphicsLayer : public GraphicsContextPainter, public WebCompositorAnimationDelegate, public WebLayerScrollClient, public cc::LayerClient { WTF_MAKE_NONCOPYABLE(GraphicsLayer); USING_FAST_MALLOC(GraphicsLayer); public: static PassOwnPtr<GraphicsLayer> create(GraphicsLayerFactory*, GraphicsLayerClient*); @@ -84,9 +84,6 @@ GraphicsLayerClient* client() const { return m_client; } - // WebLayerClient implementation. - WebGraphicsLayerDebugInfo* takeDebugInfoFor(WebLayer*) override; - GraphicsLayerDebugInfo& debugInfo(); void setCompositingReasons(CompositingReasons); @@ -246,6 +243,7 @@ static void unregisterContentsLayer(WebLayer*); // GraphicsContextPainter implementation. + IntRect interestRect(); void paint(GraphicsContext&, const IntRect* interestRect) override; // WebCompositorAnimationDelegate implementation. @@ -255,6 +253,9 @@ // WebLayerScrollClient implementation. void didScroll() override; + // cc::LayerClient implementation. + scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(cc::Layer*) override; + PaintController* paintController() override; // Exposed for tests. @@ -267,7 +268,7 @@ String debugName() const { return m_client->debugName(this); } protected: - String debugName(WebLayer*) const; + String debugName(cc::Layer*) const; explicit GraphicsLayer(GraphicsLayerClient*); // GraphicsLayerFactoryChromium that wants to create a GraphicsLayer need to be friends.
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp index 4c2c76e..6e60f15 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.cpp
@@ -20,8 +20,7 @@ #include "config.h" #include "platform/graphics/GraphicsLayerDebugInfo.h" -#include "public/platform/WebGraphicsLayerDebugInfo.h" -#include "wtf/text/CString.h" +#include "base/trace_event/trace_event_argument.h" namespace blink { @@ -33,69 +32,50 @@ GraphicsLayerDebugInfo::~GraphicsLayerDebugInfo() { } -void GraphicsLayerDebugInfo::appendAsTraceFormat(WebString* out) const +scoped_refptr<base::trace_event::TracedValue> GraphicsLayerDebugInfo::asTracedValue() const { - RefPtr<JSONObject> jsonObject = JSONObject::create(); - appendAnnotatedInvalidateRects(jsonObject.get()); - appendCompositingReasons(jsonObject.get()); - appendDebugName(jsonObject.get()); - appendOwnerNodeId(jsonObject.get()); - *out = jsonObject->toJSONString(); + scoped_refptr<base::trace_event::TracedValue> tracedValue = new base::trace_event::TracedValue; + appendAnnotatedInvalidateRects(tracedValue.get()); + appendCompositingReasons(tracedValue.get()); + appendOwnerNodeId(tracedValue.get()); + return tracedValue; } -GraphicsLayerDebugInfo* GraphicsLayerDebugInfo::clone() const +void GraphicsLayerDebugInfo::appendAnnotatedInvalidateRects(base::trace_event::TracedValue* tracedValue) const { - GraphicsLayerDebugInfo* toReturn = new GraphicsLayerDebugInfo(); - toReturn->setCompositingReasons(m_compositingReasons); - toReturn->setOwnerNodeId(m_ownerNodeId); - toReturn->m_invalidations = m_invalidations; - toReturn->m_previousInvalidations = m_previousInvalidations; - return toReturn; -} - -void GraphicsLayerDebugInfo::appendAnnotatedInvalidateRects(JSONObject* jsonObject) const -{ - RefPtr<JSONArray> jsonArray = JSONArray::create(); + tracedValue->BeginArray("annotated_invalidation_rects"); for (const auto& annotatedRect : m_previousInvalidations) { - RefPtr<JSONObject> rectContainer = JSONObject::create(); - RefPtr<JSONArray> rectArray = JSONArray::create(); const FloatRect& rect = annotatedRect.rect; - rectArray->pushNumber(rect.x()); - rectArray->pushNumber(rect.y()); - rectArray->pushNumber(rect.width()); - rectArray->pushNumber(rect.height()); - rectContainer->setArray("geometry_rect", rectArray); - rectContainer->setString("reason", paintInvalidationReasonToString(annotatedRect.reason)); - jsonArray->pushObject(rectContainer); + tracedValue->BeginDictionary(); + tracedValue->BeginArray("geometry_rect"); + tracedValue->AppendDouble(rect.x()); + tracedValue->AppendDouble(rect.y()); + tracedValue->AppendDouble(rect.width()); + tracedValue->AppendDouble(rect.height()); + tracedValue->EndArray(); + tracedValue->SetString("reason", paintInvalidationReasonToString(annotatedRect.reason)); + tracedValue->EndDictionary(); } - jsonObject->setArray("annotated_invalidation_rects", jsonArray); + tracedValue->EndArray(); } -void GraphicsLayerDebugInfo::appendCompositingReasons(JSONObject* jsonObject) const +void GraphicsLayerDebugInfo::appendCompositingReasons(base::trace_event::TracedValue* tracedValue) const { - RefPtr<JSONArray> jsonArray = JSONArray::create(); + tracedValue->BeginArray("compositing_reasons"); for (size_t i = 0; i < kNumberOfCompositingReasons; ++i) { if (!(m_compositingReasons & kCompositingReasonStringMap[i].reason)) continue; - jsonArray->pushString(kCompositingReasonStringMap[i].description); + tracedValue->AppendString(kCompositingReasonStringMap[i].description); } - jsonObject->setArray("compositing_reasons", jsonArray); + tracedValue->EndArray(); } -void GraphicsLayerDebugInfo::appendDebugName(JSONObject* jsonObject) const -{ - if (m_debugName.isEmpty()) - return; - - jsonObject->setString("layer_name", m_debugName); -} - -void GraphicsLayerDebugInfo::appendOwnerNodeId(JSONObject* jsonObject) const +void GraphicsLayerDebugInfo::appendOwnerNodeId(base::trace_event::TracedValue* tracedValue) const { if (!m_ownerNodeId) return; - jsonObject->setNumber("owner_node", m_ownerNodeId); + tracedValue->SetInteger("owner_node", m_ownerNodeId); } void GraphicsLayerDebugInfo::appendAnnotatedInvalidateRect(const FloatRect& rect, PaintInvalidationReason invalidationReason)
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.h index be57a28..b5ebc2c 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.h +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerDebugInfo.h
@@ -31,26 +31,27 @@ #ifndef GraphicsLayerDebugInfo_h #define GraphicsLayerDebugInfo_h -#include "platform/JSONValues.h" +#include "base/memory/ref_counted.h" #include "platform/geometry/FloatRect.h" #include "platform/graphics/CompositingReasons.h" #include "platform/graphics/PaintInvalidationReason.h" -#include "public/platform/WebGraphicsLayerDebugInfo.h" - #include "wtf/Vector.h" +namespace base { +namespace trace_event { +class TracedValue; +} +} + namespace blink { -class GraphicsLayerDebugInfo final : public WebGraphicsLayerDebugInfo { +class GraphicsLayerDebugInfo { public: GraphicsLayerDebugInfo(); - ~GraphicsLayerDebugInfo() override; + ~GraphicsLayerDebugInfo(); - void appendAsTraceFormat(WebString* out) const override; + scoped_refptr<base::trace_event::TracedValue> asTracedValue() const; - GraphicsLayerDebugInfo* clone() const; - - void setDebugName(const String& name) { m_debugName = name; } CompositingReasons compositingReasons() const { return m_compositingReasons; } void setCompositingReasons(CompositingReasons reasons) { m_compositingReasons = reasons; } void setOwnerNodeId(int id) { m_ownerNodeId = id; } @@ -59,17 +60,15 @@ void clearAnnotatedInvalidateRects(); private: - void appendAnnotatedInvalidateRects(JSONObject*) const; - void appendCompositingReasons(JSONObject*) const; - void appendDebugName(JSONObject*) const; - void appendOwnerNodeId(JSONObject*) const; + void appendAnnotatedInvalidateRects(base::trace_event::TracedValue*) const; + void appendCompositingReasons(base::trace_event::TracedValue*) const; + void appendOwnerNodeId(base::trace_event::TracedValue*) const; struct AnnotatedInvalidationRect { FloatRect rect; PaintInvalidationReason reason; }; - String m_debugName; CompositingReasons m_compositingReasons; int m_ownerNodeId; Vector<AnnotatedInvalidationRect> m_invalidations;
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp index 4972286..6ae446f 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
@@ -35,10 +35,9 @@ #include "platform/graphics/GraphicsContext.h" #include "platform/graphics/ImageBuffer.h" #include "platform/graphics/StaticBitmapImage.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkDevice.h" #include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/core/SkPicture.h" + +class SkPicture; namespace blink {
diff --git a/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp index bd51ccd..465ed70 100644 --- a/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp +++ b/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp
@@ -31,11 +31,11 @@ #include "config.h" #include "platform/graphics/UnacceleratedImageBufferSurface.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkDevice.h" #include "third_party/skia/include/core/SkSurface.h" #include "wtf/PassRefPtr.h" +class SkCanvas; + namespace blink { UnacceleratedImageBufferSurface::UnacceleratedImageBufferSurface(const IntSize& size, OpacityMode opacityMode, ImageInitializationMode initializationMode)
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp index 54e1e20..f7a1a94 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
@@ -33,10 +33,7 @@ #include "public/platform/Platform.h" #include "public/platform/WebGraphicsContext3DProvider.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkDevice.h" -#include "third_party/skia/include/gpu/GrRenderTarget.h" -#include "third_party/skia/include/gpu/GrTexture.h" +#include "third_party/skia/include/gpu/GrContext.h" #include "wtf/PassOwnPtr.h" #include "wtf/RefPtr.h"
diff --git a/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md b/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md index 0dc0c66..bd9c18e 100644 --- a/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md +++ b/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md
@@ -99,7 +99,7 @@ A pre-finalizer must have the following function signature: `void preFinalizer()`. You can change the function name. A pre-finalizer must be registered in the constructor by using the following statement: -"`ThreadState::current()->registerPreFinalizer(this, preFinalizerName);`". +"`ThreadState::current()->registerPreFinalizer(preFinalizerName);`". ```c++ class YourClass : public GarbageCollectedFinalized<YourClass> { @@ -107,7 +107,7 @@ public: YourClass() { - ThreadState::current()->registerPreFinalizer(this, dispose); + ThreadState::current()->registerPreFinalizer(dispose); } void dispose() {
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.h b/third_party/WebKit/Source/platform/heap/ThreadState.h index 17bb942..576519cd 100644 --- a/third_party/WebKit/Source/platform/heap/ThreadState.h +++ b/third_party/WebKit/Source/platform/heap/ThreadState.h
@@ -92,7 +92,7 @@ // public: // Foo() // { -// ThreadState::current()->registerPreFinalizer(this, dispose); +// ThreadState::current()->registerPreFinalizer(dispose); // } // private: // void dispose()
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp index 60bb9dc..f7765c3 100644 --- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp
@@ -297,7 +297,7 @@ { 2, 2, 7, 16, ImageFrame::DisposeKeep, ImageFrame::BlendAtopPreviousFrame, 1000u, true }, }; - for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(frameParameters); ++i) { const ImageFrame* const frame = decoder->frameBufferAtIndex(i); EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); EXPECT_EQ(canvasWidth, frame->getSkBitmap().width()); @@ -312,7 +312,7 @@ EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha()); } - EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount()); + EXPECT_EQ(WTF_ARRAY_LENGTH(frameParameters), decoder->frameCount()); EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); } @@ -340,7 +340,7 @@ { 10, 54, 32, 33, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::BlendAtopPreviousFrame, 1000u, true }, }; - for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(frameParameters); ++i) { const ImageFrame* const frame = decoder->frameBufferAtIndex(i); EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); EXPECT_EQ(canvasWidth, frame->getSkBitmap().width()); @@ -355,7 +355,7 @@ EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha()); } - EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount()); + EXPECT_EQ(WTF_ARRAY_LENGTH(frameParameters), decoder->frameCount()); EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); } @@ -383,7 +383,7 @@ { 10, 54, 32, 33, ImageFrame::DisposeOverwriteBgcolor, ImageFrame::BlendAtopBgcolor, 1000u, true }, }; - for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(frameParameters); ++i) { const ImageFrame* const frame = decoder->frameBufferAtIndex(i); EXPECT_EQ(ImageFrame::FrameComplete, frame->status()); EXPECT_EQ(canvasWidth, frame->getSkBitmap().width()); @@ -398,7 +398,7 @@ EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha()); } - EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount()); + EXPECT_EQ(WTF_ARRAY_LENGTH(frameParameters), decoder->frameCount()); EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount()); }
diff --git a/third_party/WebKit/Source/platform/text/BidiResolver.h b/third_party/WebKit/Source/platform/text/BidiResolver.h index 0bc9220..4bb3206 100644 --- a/third_party/WebKit/Source/platform/text/BidiResolver.h +++ b/third_party/WebKit/Source/platform/text/BidiResolver.h
@@ -178,9 +178,12 @@ VisualRightToLeftOverride }; +class NoIsolatedRun { +}; + // BidiResolver is WebKit's implementation of the Unicode Bidi Algorithm // http://unicode.org/reports/tr9 -template <class Iterator, class Run> class BidiResolver { +template <class Iterator, class Run, class IsolatedRun = NoIsolatedRun> class BidiResolver { WTF_MAKE_NONCOPYABLE(BidiResolver); public: BidiResolver() @@ -243,7 +246,7 @@ // It's unclear if this is still needed. void markCurrentRunEmpty() { m_emptyRun = true; } - Vector<Run*>& isolatedRuns() { return m_isolatedRuns; } + Vector<IsolatedRun>& isolatedRuns() { return m_isolatedRuns; } bool isEndOfLine(const Iterator& end) { return m_current == end || m_current.atEnd(); } @@ -258,8 +261,8 @@ return determineDirectionalityInternal(breakOnParagraph, hasStrongDirectionality); } - void setMidpointStateForIsolatedRun(Run*, const MidpointState<Iterator>&); - MidpointState<Iterator> midpointStateForIsolatedRun(Run*); + void setMidpointStateForIsolatedRun(Run&, const MidpointState<Iterator>&); + MidpointState<Iterator> midpointStateForIsolatedRun(Run&); Iterator endOfLine() const { return m_endOfLine; } @@ -294,7 +297,7 @@ MidpointState<Iterator> m_midpointState; unsigned m_nestedIsolateCount; - Vector<Run*> m_isolatedRuns; + Vector<IsolatedRun> m_isolatedRuns; Run* m_trailingSpaceRun; TextDirection m_paragraphDirectionality; @@ -318,16 +321,16 @@ }; #if ENABLE(ASSERT) -template <class Iterator, class Run> -BidiResolver<Iterator, Run>::~BidiResolver() +template <class Iterator, class Run, class IsolatedRun> +BidiResolver<Iterator, Run, IsolatedRun>::~BidiResolver() { // The owner of this resolver should have handled the isolated runs. ASSERT(m_isolatedRuns.isEmpty()); } #endif -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::appendRun(BidiRunList<Run>& runs) +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::appendRun(BidiRunList<Run>& runs) { if (!m_emptyRun && !m_eor.atEnd()) { unsigned startOffset = m_sor.offset(); @@ -361,8 +364,8 @@ m_status.eor = WTF::Unicode::OtherNeutral; } -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source) +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source) { // Isolated spans compute base directionality during their own UBA run. // Do not insert fake embed characters once we enter an isolated span. @@ -373,8 +376,8 @@ m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source)); } -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel() +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::checkDirectionInLowerRaiseEmbeddingLevel() { using namespace WTF::Unicode; @@ -390,8 +393,8 @@ m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft; } -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from) +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::lowerExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from) { using namespace WTF::Unicode; @@ -428,8 +431,8 @@ m_eor = Iterator(); } -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from, WTF::Unicode::Direction to) +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::raiseExplicitEmbeddingLevel(BidiRunList<Run>& runs, WTF::Unicode::Direction from, WTF::Unicode::Direction to) { using namespace WTF::Unicode; @@ -467,8 +470,8 @@ m_eor = Iterator(); } -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::applyL1Rule(BidiRunList<Run>& runs) +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::applyL1Rule(BidiRunList<Run>& runs) { ASSERT(runs.runCount()); if (!needsToApplyL1Rule(runs)) @@ -506,8 +509,8 @@ m_trailingSpaceRun = trailingSpaceRun; } -template <class Iterator, class Run> -bool BidiResolver<Iterator, Run>::commitExplicitEmbedding(BidiRunList<Run>& runs) +template <class Iterator, class Run, class IsolatedRun> +bool BidiResolver<Iterator, Run, IsolatedRun>::commitExplicitEmbedding(BidiRunList<Run>& runs) { // When we're "inIsolate()" we're resolving the parent context which // ignores (skips over) the isolated content, including embedding levels. @@ -551,8 +554,8 @@ return fromLevel != toLevel; } -template <class Iterator, class Run> -inline void BidiResolver<Iterator, Run>::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent) +template <class Iterator, class Run, class IsolatedRun> +inline void BidiResolver<Iterator, Run, IsolatedRun>::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent) { using namespace WTF::Unicode; switch (dirCurrent) { @@ -593,8 +596,8 @@ } } -template <class Iterator, class Run> -inline void BidiResolver<Iterator, Run>::reorderRunsFromLevels(BidiRunList<Run>& runs) const +template <class Iterator, class Run, class IsolatedRun> +inline void BidiResolver<Iterator, Run, IsolatedRun>::reorderRunsFromLevels(BidiRunList<Run>& runs) const { unsigned char levelLow = BidiContext::kMaxLevel; unsigned char levelHigh = 0; @@ -630,8 +633,8 @@ } } -template <class Iterator, class Run> -TextDirection BidiResolver<Iterator, Run>::determineDirectionalityInternal( +template <class Iterator, class Run, class IsolatedRun> +TextDirection BidiResolver<Iterator, Run, IsolatedRun>::determineDirectionalityInternal( bool breakOnParagraph, bool* hasStrongDirectionality) { while (!m_current.atEnd()) { @@ -682,8 +685,8 @@ return LTR; } -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak, bool reorderRuns) +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak, bool reorderRuns) { using namespace WTF::Unicode; @@ -714,7 +717,7 @@ m_last = m_current; bool lastLineEnded = false; - BidiResolver<Iterator, Run> stateAtEnd; + BidiResolver<Iterator, Run, IsolatedRun> stateAtEnd; while (true) { if (inIsolate() && m_emptyRun) { @@ -1091,20 +1094,19 @@ applyL1Rule(m_runs); } -template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::setMidpointStateForIsolatedRun(Run* run, const MidpointState<Iterator>& midpoint) +template <class Iterator, class Run, class IsolatedRun> +void BidiResolver<Iterator, Run, IsolatedRun>::setMidpointStateForIsolatedRun(Run& run, const MidpointState<Iterator>& midpoint) { - ASSERT(!m_midpointStateForIsolatedRun.contains(run)); - m_midpointStateForIsolatedRun.add(run, midpoint); + ASSERT(!m_midpointStateForIsolatedRun.contains(&run)); + m_midpointStateForIsolatedRun.add(&run, midpoint); } -template<class Iterator, class Run> -MidpointState<Iterator> BidiResolver<Iterator, Run>::midpointStateForIsolatedRun(Run* run) +template<class Iterator, class Run, class IsolatedRun> +MidpointState<Iterator> BidiResolver<Iterator, Run, IsolatedRun>::midpointStateForIsolatedRun(Run& run) { - return m_midpointStateForIsolatedRun.take(run); + return m_midpointStateForIsolatedRun.take(&run); } - } // namespace blink #endif // BidiResolver_h
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn index f19d290..b32d00f 100644 --- a/third_party/WebKit/Source/web/BUILD.gn +++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -27,6 +27,7 @@ "//third_party/WebKit/Source/platform", "//third_party/angle:translator", "//third_party/icu", + "//ui/gfx/geometry", "//v8", ]
diff --git a/third_party/WebKit/Source/web/DEPS b/third_party/WebKit/Source/web/DEPS index 907ed18..5eaa97e 100644 --- a/third_party/WebKit/Source/web/DEPS +++ b/third_party/WebKit/Source/web/DEPS
@@ -12,5 +12,6 @@ "+skia", "+third_party/khronos", "+third_party/skia", + "+ui/gfx/geometry", "+web", ]
diff --git a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp index 7f43290..1c1abfe 100644 --- a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp +++ b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
@@ -108,6 +108,21 @@ namespace blink { +namespace { + +// Convenience helper for frame tree helpers in FrameClient to reduce the amount +// of null-checking boilerplate code. Since the frame tree is maintained in the +// web/ layer, the frame tree helpers often have to deal with null WebFrames: +// for example, a frame with no parent will return null for WebFrame::parent(). +// TODO(dcheng): Remove duplication between FrameLoaderClientImpl and +// RemoteFrameClientImpl somehow... +Frame* toCoreFrame(WebFrame* frame) +{ + return frame ? frame->toImplBase()->frame() : nullptr; +} + +} // namespace + FrameLoaderClientImpl::FrameLoaderClientImpl(WebLocalFrameImpl* frame) : m_webFrame(frame) {
diff --git a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp index ce39f386..8daaf68 100644 --- a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp +++ b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
@@ -53,6 +53,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/utils/SkMatrix44.h" +#include "ui/gfx/geometry/rect.h" #include "web/WebLocalFrameImpl.h" #include "web/WebSettingsImpl.h" #include "web/WebViewImpl.h" @@ -260,6 +261,11 @@ return pathHasChanged; } +gfx::Rect LinkHighlightImpl::paintableRegion() +{ + return gfx::Rect(0, 0, contentLayer()->layer()->bounds().width, contentLayer()->layer()->bounds().height); +} + void LinkHighlightImpl::paintContents(WebDisplayItemList* webDisplayItemList, const WebRect& webClipRect, WebContentLayerClient::PaintingControlSetting paintingControl) { if (!m_node || !m_node->layoutObject())
diff --git a/third_party/WebKit/Source/web/LinkHighlightImpl.h b/third_party/WebKit/Source/web/LinkHighlightImpl.h index 64235b7..c4d6039 100644 --- a/third_party/WebKit/Source/web/LinkHighlightImpl.h +++ b/third_party/WebKit/Source/web/LinkHighlightImpl.h
@@ -60,6 +60,7 @@ void updateGeometry(); // WebContentLayerClient implementation. + gfx::Rect paintableRegion() override; void paintContents(WebDisplayItemList*, const WebRect& clipRect, WebContentLayerClient::PaintingControlSetting) override; // WebCompositorAnimationDelegate implementation.
diff --git a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp index e67b4f4a..9250810 100644 --- a/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp +++ b/third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp
@@ -21,6 +21,21 @@ namespace blink { +namespace { + +// Convenience helper for frame tree helpers in FrameClient to reduce the amount +// of null-checking boilerplate code. Since the frame tree is maintained in the +// web/ layer, the frame tree helpers often have to deal with null WebFrames: +// for example, a frame with no parent will return null for WebFrame::parent(). +// TODO(dcheng): Remove duplication between FrameLoaderClientImpl and +// RemoteFrameClientImpl somehow... +Frame* toCoreFrame(WebFrame* frame) +{ + return frame ? frame->toImplBase()->frame() : nullptr; +} + +} // namespace + RemoteFrameClientImpl::RemoteFrameClientImpl(WebRemoteFrameImpl* webFrame) : m_webFrame(webFrame) { @@ -147,7 +162,7 @@ // implemented, since this code path will need to be removed or refactored // anyway. // See https://crbug.com/520705. - if (!toCoreFrame(m_webFrame)->ownerLayoutObject()) + if (!m_webFrame->toImplBase()->frame()->ownerLayoutObject()) return; // This is only called when we have out-of-process iframes, which @@ -157,9 +172,9 @@ if (event->isKeyboardEvent()) webEvent = adoptPtr(new WebKeyboardEventBuilder(*static_cast<KeyboardEvent*>(event))); else if (event->isMouseEvent()) - webEvent = adoptPtr(new WebMouseEventBuilder(m_webFrame->frame()->view(), toCoreFrame(m_webFrame)->ownerLayoutObject(), *static_cast<MouseEvent*>(event))); + webEvent = adoptPtr(new WebMouseEventBuilder(m_webFrame->frame()->view(), m_webFrame->toImplBase()->frame()->ownerLayoutObject(), *static_cast<MouseEvent*>(event))); else if (event->isWheelEvent()) - webEvent = adoptPtr(new WebMouseWheelEventBuilder(m_webFrame->frame()->view(), toCoreFrame(m_webFrame)->ownerLayoutObject(), *static_cast<WheelEvent*>(event))); + webEvent = adoptPtr(new WebMouseWheelEventBuilder(m_webFrame->frame()->view(), m_webFrame->toImplBase()->frame()->ownerLayoutObject(), *static_cast<WheelEvent*>(event))); // Other or internal Blink events should not be forwarded. if (!webEvent || webEvent->type == WebInputEvent::Undefined)
diff --git a/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp b/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp index e45cafe..d875e5c1 100644 --- a/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp +++ b/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp
@@ -49,7 +49,7 @@ { DOMWindow* window = nullptr; if (sourceFrame) - window = toCoreFrame(sourceFrame)->domWindow(); + window = sourceFrame->toImplBase()->frame()->domWindow(); MessagePortArray* ports = nullptr; if (!targetDocument.isNull()) { RefPtrWillBeRawPtr<Document> coreDocument = PassRefPtrWillBeRawPtr<Document>(targetDocument);
diff --git a/third_party/WebKit/Source/web/WebFrame.cpp b/third_party/WebKit/Source/web/WebFrame.cpp index 5479891f..52f55905 100644 --- a/third_party/WebKit/Source/web/WebFrame.cpp +++ b/third_party/WebKit/Source/web/WebFrame.cpp
@@ -26,23 +26,12 @@ namespace blink { -Frame* toCoreFrame(const WebFrame* frame) -{ - if (!frame) - return 0; - - return frame->isWebLocalFrame() - ? static_cast<Frame*>(toWebLocalFrameImpl(frame)->frame()) - : toWebRemoteFrameImpl(frame)->frame(); -} - bool WebFrame::swap(WebFrame* frame) { using std::swap; - RefPtrWillBeRawPtr<Frame> oldFrame = toCoreFrame(this); + RefPtrWillBeRawPtr<Frame> oldFrame = toImplBase()->frame(); #if !ENABLE(OILPAN) - RefPtrWillBeRawPtr<WebLocalFrameImpl> protectWebLocalFrame = isWebLocalFrame() ? toWebLocalFrameImpl(this) : nullptr; - RefPtrWillBeRawPtr<WebRemoteFrameImpl> protectWebRemoteFrame = isWebRemoteFrame() ? toWebRemoteFrameImpl(this) : nullptr; + RefPtr<WebFrameImplBase> protectThis = toImplBase(); #endif // Unload the current Document in this frame: this calls unload handlers, @@ -113,10 +102,10 @@ localFrame.page()->setMainFrame(&localFrame); } } else { - toWebRemoteFrameImpl(frame)->initializeCoreFrame(host, owner, name); + toWebRemoteFrameImpl(frame)->initializeCoreFrame(host, owner, name, nullAtom); } - toCoreFrame(frame)->windowProxyManager()->setGlobals(globals); + frame->toImplBase()->frame()->windowProxyManager()->setGlobals(globals); m_parent = nullptr; @@ -125,12 +114,12 @@ void WebFrame::detach() { - toCoreFrame(this)->detach(FrameDetachType::Remove); + toImplBase()->frame()->detach(FrameDetachType::Remove); } WebSecurityOrigin WebFrame::securityOrigin() const { - return WebSecurityOrigin(toCoreFrame(this)->securityContext()->securityOrigin()); + return WebSecurityOrigin(toImplBase()->frame()->securityContext()->securityOrigin()); } @@ -138,7 +127,7 @@ { // At the moment, this is only used to replicate sandbox flags // for frames with a remote owner. - FrameOwner* owner = toCoreFrame(this)->owner(); + FrameOwner* owner = toImplBase()->frame()->owner(); ASSERT(owner); toRemoteBridgeFrameOwner(owner)->setSandboxFlags(static_cast<SandboxFlags>(flags)); } @@ -180,8 +169,8 @@ m_lastChild = newChild; } - toCoreFrame(this)->tree().invalidateScopedChildCount(); - toCoreFrame(this)->host()->incrementSubframeCount(); + toImplBase()->frame()->tree().invalidateScopedChildCount(); + toImplBase()->frame()->host()->incrementSubframeCount(); } void WebFrame::appendChild(WebFrame* child) @@ -207,8 +196,8 @@ child->m_previousSibling = child->m_nextSibling = 0; - toCoreFrame(this)->tree().invalidateScopedChildCount(); - toCoreFrame(this)->host()->decrementSubframeCount(); + toImplBase()->frame()->tree().invalidateScopedChildCount(); + toImplBase()->frame()->host()->decrementSubframeCount(); } void WebFrame::setParent(WebFrame* parent) @@ -251,21 +240,21 @@ WebFrame* WebFrame::traversePrevious(bool wrap) const { - if (Frame* frame = toCoreFrame(this)) + if (Frame* frame = toImplBase()->frame()) return fromFrame(frame->tree().traversePreviousWithWrap(wrap)); return 0; } WebFrame* WebFrame::traverseNext(bool wrap) const { - if (Frame* frame = toCoreFrame(this)) + if (Frame* frame = toImplBase()->frame()) return fromFrame(frame->tree().traverseNextWithWrap(wrap)); return 0; } WebFrame* WebFrame::findChildByName(const WebString& name) const { - Frame* frame = toCoreFrame(this); + Frame* frame = toImplBase()->frame(); if (!frame) return 0; // FIXME: It's not clear this should ever be called to find a remote frame. @@ -284,7 +273,7 @@ bool WebFrame::isLoading() const { - if (Frame* frame = toCoreFrame(this)) + if (Frame* frame = toImplBase()->frame()) return frame->isLoading(); return false; }
diff --git a/third_party/WebKit/Source/web/WebFrameImplBase.cpp b/third_party/WebKit/Source/web/WebFrameImplBase.cpp new file mode 100644 index 0000000..6254074 --- /dev/null +++ b/third_party/WebKit/Source/web/WebFrameImplBase.cpp
@@ -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 "config.h" +#include "web/WebFrameImplBase.h" + +#include "platform/heap/Handle.h" + +namespace blink { + +WebFrameImplBase::~WebFrameImplBase() +{ +} + +DEFINE_TRACE(WebFrameImplBase) +{ +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/web/WebFrameImplBase.h b/third_party/WebKit/Source/web/WebFrameImplBase.h new file mode 100644 index 0000000..033ef5b --- /dev/null +++ b/third_party/WebKit/Source/web/WebFrameImplBase.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 WebFrameImplBase_h +#define WebFrameImplBase_h + +#include "platform/heap/Handle.h" +#include "wtf/text/AtomicString.h" + +namespace blink { + +class Frame; +class FrameHost; +class FrameOwner; + +// WebFrameImplBase exists to avoid the diamond inheritance problem: +// - The public interfaces WebLocalFrame/WebRemoteFrame extend WebFrame. +// - WebLocalFrameImpl implements WebLocalFrame and WebRemoteFrameImpl +// implements WebRemoteFrame. +// - The private implementations should share some functionality, but cannot +// inherit from a common base class inheriting WebFrame. This would result in +// WebFrame beind inherited from two different base classes. +// +// To get around this, only the private implementations have WebFrameImplBase as +// a base class. WebFrame exposes a virtual accessor to retrieve the underlying +// implementation as an instance of the base class, but has no inheritance +// relationship with it. The cost is a virtual indirection, but this is nicer +// than the previous manual dispatch emulating real virtual dispatch. +class WebFrameImplBase : public RefCountedWillBeGarbageCollectedFinalized<WebFrameImplBase> { +public: + virtual ~WebFrameImplBase(); + + virtual void initializeCoreFrame(FrameHost*, FrameOwner*, const AtomicString& name, const AtomicString& fallbackName) = 0; + // TODO(dcheng): Rename this to coreFrame()? This probably also shouldn't be const... + virtual Frame* frame() const = 0; + + DECLARE_VIRTUAL_TRACE(); +}; + +} // namespace blink + +#endif // WebFrameImplBase_h
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index 94cae36..c8c83ee 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -1016,7 +1016,7 @@ PaintLayerCompositor* WebFrameWidgetImpl::compositor() const { - LocalFrame* frame = toLocalFrame(toCoreFrame(m_localRoot)); + LocalFrame* frame = m_localRoot->frame(); if (!frame || !frame->document() || !frame->document()->layoutView()) return nullptr;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index 4cb7d027..44a1e9b 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -944,7 +944,7 @@ bool WebFrame::scriptCanAccess(WebFrame* target) { - return BindingSecurity::shouldAllowAccessToFrame(mainThreadIsolate(), callingDOMWindow(mainThreadIsolate()), toCoreFrame(target), DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessToFrame(mainThreadIsolate(), callingDOMWindow(mainThreadIsolate()), target->toImplBase()->frame(), DoNotReportSecurityError); } void WebLocalFrameImpl::reload(bool ignoreCache) @@ -1682,6 +1682,7 @@ visitor->trace(m_geolocationClientProxy); visitor->template registerWeakMembers<WebFrame, &WebFrame::clearWeakFrames>(this); WebFrame::traceFrames(visitor, this); + WebFrameImplBase::trace(visitor); } #endif @@ -1721,16 +1722,14 @@ } } -PassRefPtrWillBeRawPtr<LocalFrame> WebLocalFrameImpl::initializeCoreFrame(FrameHost* host, FrameOwner* owner, const AtomicString& name, const AtomicString& fallbackName) +void WebLocalFrameImpl::initializeCoreFrame(FrameHost* host, FrameOwner* owner, const AtomicString& name, const AtomicString& fallbackName) { - RefPtrWillBeRawPtr<LocalFrame> frame = LocalFrame::create(m_frameLoaderClientImpl.get(), host, owner); - setCoreFrame(frame); - frame->tree().setName(name, fallbackName); + setCoreFrame(LocalFrame::create(m_frameLoaderClientImpl.get(), host, owner)); + frame()->tree().setName(name, fallbackName); // We must call init() after m_frame is assigned because it is referenced // during init(). Note that this may dispatch JS events; the frame may be // detached after init() returns. - frame->init(); - return frame; + frame()->init(); } PassRefPtrWillBeRawPtr<LocalFrame> WebLocalFrameImpl::createChildFrame(const FrameLoadRequest& request, @@ -1742,7 +1741,7 @@ ? WebTreeScopeType::Document : WebTreeScopeType::Shadow; WebFrameOwnerProperties ownerProperties(ownerElement->scrollingMode(), ownerElement->marginWidth(), ownerElement->marginHeight()); - WebLocalFrameImpl* webframeChild = toWebLocalFrameImpl(m_client->createChildFrame(this, scope, name, static_cast<WebSandboxFlags>(ownerElement->sandboxFlags()), ownerProperties)); + RefPtrWillBeRawPtr<WebLocalFrameImpl> webframeChild = toWebLocalFrameImpl(m_client->createChildFrame(this, scope, name, static_cast<WebSandboxFlags>(ownerElement->sandboxFlags()), ownerProperties)); if (!webframeChild) return nullptr; @@ -1750,17 +1749,17 @@ // solution. subResourceAttributeName returns just one attribute name. The // element might not have the attribute, and there might be other attributes // which can identify the element. - RefPtrWillBeRawPtr<LocalFrame> child = webframeChild->initializeCoreFrame(frame()->host(), ownerElement, name, ownerElement->getAttribute(ownerElement->subResourceAttributeName())); + webframeChild->initializeCoreFrame(frame()->host(), ownerElement, name, ownerElement->getAttribute(ownerElement->subResourceAttributeName())); // Initializing the core frame may cause the new child to be detached, since // it may dispatch a load event in the parent. - if (!child->tree().parent()) + if (!webframeChild->parent()) return nullptr; // If we're moving in the back/forward list, we might want to replace the content // of this child frame with whatever was there at that point. RefPtrWillBeRawPtr<HistoryItem> childItem = nullptr; if (isBackForwardLoadType(frame()->loader().loadType()) && !frame()->document()->loadEventFinished()) - childItem = PassRefPtrWillBeRawPtr<HistoryItem>(webframeChild->client()->historyItemForNewChildFrame(webframeChild)); + childItem = PassRefPtrWillBeRawPtr<HistoryItem>(webframeChild->client()->historyItemForNewChildFrame(webframeChild.get())); FrameLoadRequest newRequest = request; FrameLoadType loadType = FrameLoadTypeStandard; @@ -1769,14 +1768,14 @@ FrameLoader::resourceRequestFromHistoryItem(childItem.get(), UseProtocolCachePolicy)); loadType = FrameLoadTypeInitialHistoryLoad; } - child->loader().load(newRequest, loadType, childItem.get()); + webframeChild->frame()->loader().load(newRequest, loadType, childItem.get()); // Note a synchronous navigation (about:blank) would have already processed // onload, so it is possible for the child frame to have already been // detached by script in the page. - if (!child->tree().parent()) + if (!webframeChild->parent()) return nullptr; - return child; + return webframeChild->frame(); } void WebLocalFrameImpl::didChangeContentsSize(const IntSize& size) @@ -1984,7 +1983,7 @@ void WebLocalFrameImpl::initializeToReplaceRemoteFrame(WebRemoteFrame* oldWebFrame, const WebString& name, WebSandboxFlags flags, const WebFrameOwnerProperties& frameOwnerProperties) { - Frame* oldFrame = toCoreFrame(oldWebFrame); + Frame* oldFrame = oldWebFrame->toImplBase()->frame(); // Note: this *always* temporarily sets a frame owner, even for main frames! // When a core Frame is created with no owner, it attempts to set itself as // the main frame of the Page. However, this is a provisional frame, and may @@ -2040,7 +2039,7 @@ { // At the moment, this is only used to replicate frame owner properties // for frames with a remote owner. - FrameOwner* owner = toCoreFrame(this)->owner(); + FrameOwner* owner = frame()->owner(); ASSERT(owner); toRemoteBridgeFrameOwner(owner)->setScrollingMode(frameOwnerProperties.scrollingMode); toRemoteBridgeFrameOwner(owner)->setMarginWidth(frameOwnerProperties.marginWidth);
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h index 79165d0..ecc3356 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -38,6 +38,7 @@ #include "public/web/WebLocalFrame.h" #include "web/FrameLoaderClientImpl.h" #include "web/UserMediaClientImpl.h" +#include "web/WebFrameImplBase.h" #include "wtf/Compiler.h" #include "wtf/OwnPtr.h" #include "wtf/RefCounted.h" @@ -72,7 +73,7 @@ template <typename T> class WebVector; // Implementation of WebFrame, note that this is a reference counted object. -class WebLocalFrameImpl final : public RefCountedWillBeGarbageCollectedFinalized<WebLocalFrameImpl>, public WebLocalFrame { +class WebLocalFrameImpl final : public WebFrameImplBase, public WebLocalFrame { public: // WebFrame methods: bool isWebLocalFrame() const override; @@ -227,6 +228,8 @@ void registerTestInterface(const WebString& name, WebTestInterfaceFactory*) override; + WebFrameImplBase* toImplBase() override { return this; } + // Creates a test interface by name if available, returns an empty handle // for unknown names. v8::Local<v8::Value> createTestInterface(const AtomicString& name); @@ -256,14 +259,16 @@ void didCallIsSearchProviderInstalled() override; void replaceSelection(const WebString&) override; + // WebFrameImplBase methods: + void initializeCoreFrame(FrameHost*, FrameOwner*, const AtomicString& name, const AtomicString& fallbackName) override; + LocalFrame* frame() const override { return m_frame.get(); } + void willBeDetached(); void willDetachParent(); static WebLocalFrameImpl* create(WebTreeScopeType, WebFrameClient*); ~WebLocalFrameImpl() override; - PassRefPtrWillBeRawPtr<LocalFrame> initializeCoreFrame(FrameHost*, FrameOwner*, const AtomicString& name, const AtomicString& fallbackName); - PassRefPtrWillBeRawPtr<LocalFrame> createChildFrame(const FrameLoadRequest&, const AtomicString& name, HTMLFrameOwnerElement*); void didChangeContentsSize(const IntSize&); @@ -318,7 +323,6 @@ // Otherwise, disallow scrolling. void setCanHaveScrollbars(bool) override; - LocalFrame* frame() const { return m_frame.get(); } WebFrameClient* client() const { return m_client; } void setClient(WebFrameClient* client) { m_client = client; }
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp index 60f6c2b2..2f38894 100644 --- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
@@ -6,7 +6,6 @@ #include "web/WebRemoteFrameImpl.h" #include "core/frame/FrameView.h" -#include "core/frame/RemoteFrame.h" #include "core/frame/Settings.h" #include "core/page/Page.h" #include "platform/heap/Handle.h" @@ -28,7 +27,7 @@ return WebRemoteFrameImpl::create(scope, client); } -WebRemoteFrame* WebRemoteFrameImpl::create(WebTreeScopeType scope, WebRemoteFrameClient* client) +WebRemoteFrameImpl* WebRemoteFrameImpl::create(WebTreeScopeType scope, WebRemoteFrameClient* client) { WebRemoteFrameImpl* frame = new WebRemoteFrameImpl(scope, client); #if ENABLE(OILPAN) @@ -50,6 +49,7 @@ visitor->trace(m_ownersForChildren); visitor->template registerWeakMembers<WebFrame, &WebFrame::clearWeakFrames>(this); WebFrame::traceFrames(visitor, this); + WebFrameImplBase::trace(visitor); } #endif @@ -717,11 +717,11 @@ } -void WebRemoteFrameImpl::initializeCoreFrame(FrameHost* host, FrameOwner* owner, const AtomicString& name) +void WebRemoteFrameImpl::initializeCoreFrame(FrameHost* host, FrameOwner* owner, const AtomicString& name, const AtomicString& fallbackName) { setCoreFrame(RemoteFrame::create(m_frameClient.get(), host, owner)); frame()->createView(); - m_frame->tree().setName(name, nullAtom); + m_frame->tree().setName(name, fallbackName); } WebRemoteFrame* WebRemoteFrameImpl::createRemoteChild(WebTreeScopeType scope, const WebString& name, WebSandboxFlags sandboxFlags, WebRemoteFrameClient* client) @@ -730,7 +730,7 @@ WillBeHeapHashMap<WebFrame*, OwnPtrWillBeMember<FrameOwner>>::AddResult result = m_ownersForChildren.add(child, RemoteBridgeFrameOwner::create(nullptr, static_cast<SandboxFlags>(sandboxFlags), WebFrameOwnerProperties())); appendChild(child); - child->initializeCoreFrame(frame()->host(), result.storedValue->value.get(), name); + child->initializeCoreFrame(frame()->host(), result.storedValue->value.get(), name, nullAtom); return child; }
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h index 2c2a59f..f18cd03 100644 --- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h +++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
@@ -6,10 +6,11 @@ #define WebRemoteFrameImpl_h #include "core/frame/FrameOwner.h" -#include "platform/heap/Handle.h" +#include "core/frame/RemoteFrame.h" #include "public/web/WebRemoteFrame.h" #include "public/web/WebRemoteFrameClient.h" #include "web/RemoteFrameClientImpl.h" +#include "web/WebFrameImplBase.h" #include "wtf/HashMap.h" #include "wtf/OwnPtr.h" #include "wtf/RefCounted.h" @@ -20,12 +21,12 @@ class FrameOwner; class RemoteFrame; -class WebRemoteFrameImpl final : public RefCountedWillBeGarbageCollectedFinalized<WebRemoteFrameImpl>, public WebRemoteFrame { +class WebRemoteFrameImpl final : public WebFrameImplBase, public WebRemoteFrame { public: - static WebRemoteFrame* create(WebTreeScopeType, WebRemoteFrameClient*); + static WebRemoteFrameImpl* create(WebTreeScopeType, WebRemoteFrameClient*); ~WebRemoteFrameImpl() override; - // WebRemoteFrame methods. + // WebFrame methods: bool isWebLocalFrame() const override; WebLocalFrame* toWebLocalFrame() override; bool isWebRemoteFrame() const override; @@ -165,18 +166,22 @@ bool selectionStartHasSpellingMarkerFor(int from, int length) const override; WebString layerTreeAsText(bool showDebugInfo = false) const override; - WebLocalFrame* createLocalChild(WebTreeScopeType, const WebString& name, WebSandboxFlags, WebFrameClient*, WebFrame* previousSibling, const WebFrameOwnerProperties&) override; - WebRemoteFrame* createRemoteChild(WebTreeScopeType, const WebString& name, WebSandboxFlags, WebRemoteFrameClient*) override; + WebFrameImplBase* toImplBase() { return this; } - void initializeCoreFrame(FrameHost*, FrameOwner*, const AtomicString& name); + // WebFrameImplBase methods: + void initializeCoreFrame(FrameHost*, FrameOwner*, const AtomicString& name, const AtomicString& fallbackName) override; + RemoteFrame* frame() const override { return m_frame.get(); } void setCoreFrame(PassRefPtrWillBeRawPtr<RemoteFrame>); - RemoteFrame* frame() const { return m_frame.get(); } WebRemoteFrameClient* client() const { return m_client; } static WebRemoteFrameImpl* fromFrame(RemoteFrame&); + // WebRemoteFrame methods: + WebLocalFrame* createLocalChild(WebTreeScopeType, const WebString& name, WebSandboxFlags, WebFrameClient*, WebFrame* previousSibling, const WebFrameOwnerProperties&) override; + WebRemoteFrame* createRemoteChild(WebTreeScopeType, const WebString& name, WebSandboxFlags, WebRemoteFrameClient*) override; + void initializeFromFrame(WebLocalFrame*) const override; void setReplicatedOrigin(const WebSecurityOrigin&) const override;
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 93970bc..fb4e60aa 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -367,12 +367,7 @@ void WebViewImpl::setMainFrame(WebFrame* frame) { - if (frame->isWebLocalFrame()) { - WebLocalFrameImpl* localFrame = toWebLocalFrameImpl(frame); - localFrame->initializeCoreFrame(&page()->frameHost(), 0, nullAtom, nullAtom); - } else { - toWebRemoteFrameImpl(frame)->initializeCoreFrame(&page()->frameHost(), 0, nullAtom); - } + frame->toImplBase()->initializeCoreFrame(&page()->frameHost(), 0, nullAtom, nullAtom); } void WebViewImpl::setCredentialManagerClient(WebCredentialManagerClient* webCredentialManagerClient) @@ -2810,7 +2805,7 @@ void WebViewImpl::focusDocumentView(WebFrame* frame) { - page()->focusController().focusDocumentView(toCoreFrame(frame)); + page()->focusController().focusDocumentView(frame->toImplBase()->frame()); } void WebViewImpl::setInitialFocus(bool reverse)
diff --git a/third_party/WebKit/Source/web/resources/listPicker.js b/third_party/WebKit/Source/web/resources/listPicker.js index 167ad3c..1f5d2e9 100644 --- a/third_party/WebKit/Source/web/resources/listPicker.js +++ b/third_party/WebKit/Source/web/resources/listPicker.js
@@ -87,7 +87,25 @@ delete window.updateData; }; +// This should be matched to the border width of the internal listbox +// SELECT. See listPicker.css and html.css. +ListPicker.ListboxSelectBorder = 1; + ListPicker.prototype._handleWindowMouseMove = function (event) { + var visibleTop = ListPicker.ListboxSelectBorder; + var visibleBottom = this._selectElement.offsetHeight - ListPicker.ListboxSelectBorder; + var optionBounds = event.target.getBoundingClientRect(); + if (optionBounds.height >= 1.0) { + // If the height of the visible part of event.target is less than 1px, + // ignore this event because it may be an error by sub-pixel layout. + if (optionBounds.top < visibleTop) { + if (optionBounds.bottom - visibleTop < 1.0) + return; + } else if (optionBounds.bottom > visibleBottom) { + if (visibleBottom - optionBounds.top < 1.0) + return; + } + } this.lastMousePositionX = event.clientX; this.lastMousePositionY = event.clientY; this._highlightOption(event.target); @@ -194,10 +212,7 @@ ListPicker.prototype._fixWindowSize = function() { this._selectElement.style.height = ""; var maxHeight = this._selectElement.offsetHeight; - // heightOutsideOfContent should be matched to border widths of the listbox - // SELECT. See listPicker.css and html.css. - var heightOutsideOfContent = 2; - var noScrollHeight = Math.round(this._calculateScrollHeight() + heightOutsideOfContent); + var noScrollHeight = Math.round(this._calculateScrollHeight() + ListPicker.ListboxSelectBorder * 2); var desiredWindowHeight = noScrollHeight; var desiredWindowWidth = this._selectElement.offsetWidth; var expectingScrollbar = false;
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp index 0c2d6422..714d720 100644 --- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp +++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
@@ -40,11 +40,11 @@ #include "public/platform/WebURLRequest.h" #include "public/platform/WebURLResponse.h" #include "public/platform/WebUnitTestSupport.h" -#include "public/web/WebRemoteFrame.h" #include "public/web/WebSettings.h" #include "public/web/WebTreeScopeType.h" #include "public/web/WebViewClient.h" #include "web/WebLocalFrameImpl.h" +#include "web/WebRemoteFrameImpl.h" #include "wtf/StdLibExtras.h" namespace blink { @@ -333,7 +333,7 @@ } TestWebRemoteFrameClient::TestWebRemoteFrameClient() - : m_frame(WebRemoteFrame::create(WebTreeScopeType::Document, this)) + : m_frame(WebRemoteFrameImpl::create(WebTreeScopeType::Document, this)) { }
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.h b/third_party/WebKit/Source/web/tests/FrameTestHelpers.h index 8507f93..dc110ad 100644 --- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.h +++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.h
@@ -47,6 +47,8 @@ namespace blink { +class WebRemoteFrameImpl; + namespace FrameTestHelpers { class TestWebFrameClient; @@ -150,7 +152,7 @@ public: TestWebRemoteFrameClient(); - WebRemoteFrame* frame() const { return m_frame; } + WebRemoteFrameImpl* frame() const { return m_frame; } // WebRemoteFrameClient overrides: void frameDetached(DetachType) override; @@ -161,7 +163,7 @@ WebDOMMessageEvent) override { } private: - WebRemoteFrame* const m_frame; + WebRemoteFrameImpl* const m_frame; }; class TestWebViewClient : public WebViewClient {
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp index 4104032..cf3d36e 100644 --- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -1394,7 +1394,7 @@ "viewport-target-densitydpi-device-and-fixed-width.html" }; float pageScaleFactors[] = { 0.5f, 1.0f }; - for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) + for (size_t i = 0; i < WTF_ARRAY_LENGTH(pages); ++i) registerMockedHttpURLLoad(pages[i]); FixedLayoutTestWebViewClient client; @@ -1403,7 +1403,7 @@ int viewportHeight = 300; float enforcedPageScaleFactor = 0.75f; - for (size_t i = 0; i < ARRAY_SIZE(pages); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(pages); ++i) { for (int quirkEnabled = 0; quirkEnabled <= 1; ++quirkEnabled) { FrameTestHelpers::WebViewHelper webViewHelper(this); webViewHelper.initializeAndLoad(m_baseURL + pages[i], true, 0, &client, enableViewportSettings); @@ -1412,7 +1412,7 @@ webViewHelper.webView()->setInitialPageScaleOverride(enforcedPageScaleFactor); webViewHelper.webView()->resize(WebSize(viewportWidth, viewportHeight)); - float expectedPageScaleFactor = quirkEnabled && i < ARRAY_SIZE(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor; + float expectedPageScaleFactor = quirkEnabled && i < WTF_ARRAY_LENGTH(pageScaleFactors) ? pageScaleFactors[i] : enforcedPageScaleFactor; EXPECT_EQ(expectedPageScaleFactor, webViewHelper.webView()->pageScaleFactor()); } } @@ -2049,7 +2049,7 @@ int viewportWidth = 640; int viewportHeight = 480; - for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(deviceScaleFactors); ++i) { float deviceScaleFactor = deviceScaleFactors[i]; float deviceDpi = deviceScaleFactor * 160.0f; client.m_screenInfo.deviceScaleFactor = deviceScaleFactor; @@ -2079,7 +2079,7 @@ int viewportWidth = 640; int viewportHeight = 480; - for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(deviceScaleFactors); ++i) { client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i]; FrameTestHelpers::WebViewHelper webViewHelper(this); @@ -2104,7 +2104,7 @@ int viewportWidth = 640; int viewportHeight = 480; - for (size_t i = 0; i < ARRAY_SIZE(deviceScaleFactors); ++i) { + for (size_t i = 0; i < WTF_ARRAY_LENGTH(deviceScaleFactors); ++i) { client.m_screenInfo.deviceScaleFactor = deviceScaleFactors[i]; FrameTestHelpers::WebViewHelper webViewHelper(this); @@ -6984,7 +6984,7 @@ WebLocalFrame* childFrame = view->mainFrame()->toWebRemoteFrame()->createLocalChild(WebTreeScopeType::Document, "", WebSandboxFlags::None, &childFrameClient, nullptr, WebFrameOwnerProperties()); // Purposely keep the LocalFrame alive so it's the last thing to be destroyed. - RefPtrWillBePersistent<Frame> childCoreFrame = toCoreFrame(childFrame); + RefPtrWillBePersistent<Frame> childCoreFrame = childFrame->toImplBase()->frame(); view->close(); childCoreFrame.clear(); } @@ -7526,7 +7526,7 @@ // the frame's window without navigating it. RefPtrWillBeRawPtr<DOMWindow> result = mainWindow->open("", "frame1", "", mainWindow, mainWindow); EXPECT_EQ(remoteClient.lastRequest().url(), WebURL(destination)); - EXPECT_EQ(result, toCoreFrame(remoteFrame)->domWindow()); + EXPECT_EQ(result, remoteFrame->toImplBase()->frame()->domWindow()); reset(); } @@ -7557,15 +7557,15 @@ // Create a remote window that will be closed later in the test. RemoteWindowCloseClient viewClient; FrameTestHelpers::TestWebRemoteFrameClient frameClient; - WebRemoteFrame* webRemoteFrame = frameClient.frame(); + WebRemoteFrameImpl* webRemoteFrame = frameClient.frame(); WebView* view = WebView::create(&viewClient); view->setMainFrame(webRemoteFrame); view->mainFrame()->setOpener(mainWebView.webView()->mainFrame()); webRemoteFrame->setReplicatedOrigin(WebSecurityOrigin::createFromString("http://127.0.0.1")); - LocalFrame* localFrame = toLocalFrame(toCoreFrame(mainWebView.webView()->mainFrame())); - RemoteFrame* remoteFrame = toRemoteFrame(toCoreFrame(frameClient.frame())); + LocalFrame* localFrame = toLocalFrame(mainWebView.webView()->mainFrame()->toImplBase()->frame()); + RemoteFrame* remoteFrame = webRemoteFrame->frame(); // Attempt to close the window, which should fail as it isn't opened // by a script. @@ -7655,7 +7655,7 @@ FrameTestHelpers::TestWebRemoteFrameClient remoteClient; WebView* view = WebView::create(&viewClient); view->setMainFrame(remoteClient.frame()); - toRemoteFrame(toCoreFrame(view->mainFrame()))->securityContext()->setReplicatedOrigin(SecurityOrigin::create(toKURL(m_baseURL))); + remoteClient.frame()->setReplicatedOrigin(WebSecurityOrigin::createFromString(WebString::fromUTF8(m_baseURL))); // If an iframe has a remote main frame, ensure the inital commit is correctly identified as WebInitialCommitInChildFrame. CommitTypeWebFrameClient childFrameClient;
diff --git a/third_party/WebKit/Source/web/web.gyp b/third_party/WebKit/Source/web/web.gyp index 245251ab..88530ca 100644 --- a/third_party/WebKit/Source/web/web.gyp +++ b/third_party/WebKit/Source/web/web.gyp
@@ -61,6 +61,7 @@ '<(angle_path)/src/angle.gyp:translator', '<(DEPTH)/third_party/icu/icu.gyp:icuuc', '<(DEPTH)/third_party/npapi/npapi.gyp:npapi', + '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry', '<(DEPTH)/v8/tools/gyp/v8.gyp:v8', ], 'export_dependent_settings': [
diff --git a/third_party/WebKit/Source/web/web.gypi b/third_party/WebKit/Source/web/web.gypi index 9c003647..eee6c0f2 100644 --- a/third_party/WebKit/Source/web/web.gypi +++ b/third_party/WebKit/Source/web/web.gypi
@@ -145,6 +145,8 @@ 'WebFontImpl.h', 'WebFormControlElement.cpp', 'WebFormElement.cpp', + 'WebFrameImplBase.cpp', + 'WebFrameImplBase.h', 'WebFrame.cpp', 'WebFrameWidgetImpl.cpp', 'WebFrameWidgetImpl.h',
diff --git a/third_party/WebKit/public/blink_headers.gypi b/third_party/WebKit/public/blink_headers.gypi index 1385663..c6a83ca 100644 --- a/third_party/WebKit/public/blink_headers.gypi +++ b/third_party/WebKit/public/blink_headers.gypi
@@ -110,7 +110,6 @@ "platform/WebGestureDevice.h", "platform/WebGraphicsContext3D.h", "platform/WebGraphicsContext3DProvider.h", - "platform/WebGraphicsLayerDebugInfo.h", "platform/WebHTTPBody.h", "platform/WebHTTPHeaderVisitor.h", "platform/WebHTTPLoadInfo.h", @@ -121,7 +120,6 @@ "platform/WebInbandTextTrack.h", "platform/WebInbandTextTrackClient.h", "platform/WebLayer.h", - "platform/WebLayerClient.h", "platform/WebLayerPositionConstraint.h", "platform/WebLayerScrollClient.h", "platform/WebLayerTreeView.h",
diff --git a/third_party/WebKit/public/platform/Platform.h b/third_party/WebKit/public/platform/Platform.h index d1713f93..9924046 100644 --- a/third_party/WebKit/public/platform/Platform.h +++ b/third_party/WebKit/public/platform/Platform.h
@@ -276,15 +276,6 @@ // Return the number of of processors of the current machine. virtual size_t numberOfProcessors() { return 0; } - // Returns private and shared usage, in bytes. Private bytes is the amount of - // memory currently allocated to this process that cannot be shared. Returns - // false on platform specific error conditions. - virtual bool processMemorySizesInBytes(size_t* privateBytes, size_t* sharedBytes) { return false; } - - // Reports number of bytes used by memory allocator for internal needs. - // Returns true if the size has been reported, or false otherwise. - virtual bool memoryAllocatorWasteInBytes(size_t*) { return false; } - // Allocates discardable memory. May return nullptr, even if the platform supports // discardable memory. If nonzero, however, then the WebDiscardableMmeory is // returned in an locked state. You may use its underlying data() member
diff --git a/third_party/WebKit/public/platform/WebContentLayerClient.h b/third_party/WebKit/public/platform/WebContentLayerClient.h index 7e28aee..f0f53e0 100644 --- a/third_party/WebKit/public/platform/WebContentLayerClient.h +++ b/third_party/WebKit/public/platform/WebContentLayerClient.h
@@ -28,10 +28,14 @@ #include "WebCommon.h" +namespace gfx { +class Rect; +} + namespace blink { -class WebDisplayItemList; struct WebRect; +class WebDisplayItemList; class BLINK_PLATFORM_EXPORT WebContentLayerClient { public: @@ -42,6 +46,8 @@ DisplayListPaintingDisabled }; + virtual gfx::Rect paintableRegion() = 0; + // Paints the content area for the layer, typically dirty rects submitted // through WebContentLayer::setNeedsDisplayInRect, submitting drawing commands // to populate the WebDisplayItemList.
diff --git a/third_party/WebKit/public/platform/WebGraphicsLayerDebugInfo.h b/third_party/WebKit/public/platform/WebGraphicsLayerDebugInfo.h deleted file mode 100644 index 15265eb..0000000 --- a/third_party/WebKit/public/platform/WebGraphicsLayerDebugInfo.h +++ /dev/null
@@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebGraphicsLayerDebugInfo_h -#define WebGraphicsLayerDebugInfo_h - -#include "public/platform/WebString.h" - -namespace blink { - -template <typename T> -class WebVector; - -class WebGraphicsLayerDebugInfo { -public: - virtual void appendAsTraceFormat(WebString* out) const = 0; - virtual ~WebGraphicsLayerDebugInfo() { } -}; - -} // namespace blink - -#endif // WebGraphicsLayerDebugInfo_h -
diff --git a/third_party/WebKit/public/platform/WebLayer.h b/third_party/WebKit/public/platform/WebLayer.h index b0ebba5..1e1f1ed 100644 --- a/third_party/WebKit/public/platform/WebLayer.h +++ b/third_party/WebKit/public/platform/WebLayer.h
@@ -42,10 +42,14 @@ class SkMatrix44; class SkImageFilter; +namespace cc { +class Layer; +class LayerClient; +} + namespace blink { class WebCompositorAnimationDelegate; class WebFilterOperations; -class WebLayerClient; class WebLayerScrollClient; struct WebFloatPoint; struct WebLayerPositionConstraint; @@ -238,7 +242,11 @@ // True if the layer is not part of a tree attached to a WebLayerTreeView. virtual bool isOrphan() const = 0; - virtual void setWebLayerClient(WebLayerClient*) = 0; + // Sets the cc-side layer client. + virtual void setLayerClient(cc::LayerClient*) = 0; + + // Gets the underlying cc layer. + virtual const cc::Layer* ccLayer() const = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebLayerClient.h b/third_party/WebKit/public/platform/WebLayerClient.h deleted file mode 100644 index 74cd3f0..0000000 --- a/third_party/WebKit/public/platform/WebLayerClient.h +++ /dev/null
@@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebLayerClient_h -#define WebLayerClient_h - -#include "WebCommon.h" - -namespace blink { - -class WebGraphicsLayerDebugInfo; - -class BLINK_PLATFORM_EXPORT WebLayerClient { -public: - // Returns a pointer to a debug info object, if one has been computed. - // If not, returns 0. If the returned pointer is non-zero, the caller takes - // ownership of the pointer. The parameter allows us to return WebLayer- - // specific information, too (only the debug name for now). - virtual WebGraphicsLayerDebugInfo* takeDebugInfoFor(WebLayer*) = 0; - -protected: - virtual ~WebLayerClient() { } -}; - -} // namespace blink - -#endif // WebLayerClient_h -
diff --git a/third_party/WebKit/public/web/WebFrame.h b/third_party/WebKit/public/web/WebFrame.h index bbecd55..c99c667 100644 --- a/third_party/WebKit/public/web/WebFrame.h +++ b/third_party/WebKit/public/web/WebFrame.h
@@ -63,6 +63,7 @@ class WebDataSource; class WebDocument; class WebElement; +class WebFrameImplBase; class WebLayer; class WebLocalFrame; class WebPerformance; @@ -679,6 +680,13 @@ // text form. This is used only by layout tests. virtual WebString layerTreeAsText(bool showDebugInfo = false) const = 0; + virtual WebFrameImplBase* toImplBase() = 0; + // TODO(dcheng): Fix const-correctness issues and remove this overload. + virtual const WebFrameImplBase* toImplBase() const + { + return const_cast<WebFrame*>(this)->toImplBase(); + } + // Returns the frame inside a given frame or iframe element. Returns 0 if // the given element is not a frame, iframe or if the frame is empty. BLINK_EXPORT static WebFrame* fromFrameOwnerElement(const WebElement&);
diff --git a/third_party/mojo/mojo_edk_tests.gyp b/third_party/mojo/mojo_edk_tests.gyp index c64e025a..376a3e4 100644 --- a/third_party/mojo/mojo_edk_tests.gyp +++ b/third_party/mojo/mojo_edk_tests.gyp
@@ -40,12 +40,14 @@ 'mojo_edk.gyp:mojo_run_all_unittests', 'mojo_public.gyp:mojo_cpp_bindings', 'mojo_public.gyp:mojo_public_bindings_test_utils', + 'mojo_public.gyp:mojo_public_test_associated_interfaces', 'mojo_public.gyp:mojo_public_test_interfaces', 'mojo_public.gyp:mojo_public_test_utils', 'mojo_public.gyp:mojo_utility', ], 'sources': [ '../../mojo/public/cpp/bindings/tests/array_unittest.cc', + '../../mojo/public/cpp/bindings/tests/associated_interface_unittest.cc', '../../mojo/public/cpp/bindings/tests/bounds_checker_unittest.cc', '../../mojo/public/cpp/bindings/tests/buffer_unittest.cc', '../../mojo/public/cpp/bindings/tests/connector_unittest.cc',
diff --git a/third_party/mojo/mojo_public.gyp b/third_party/mojo/mojo_public.gyp index 63c9b0ad..32edb136 100644 --- a/third_party/mojo/mojo_public.gyp +++ b/third_party/mojo/mojo_public.gyp
@@ -97,6 +97,11 @@ ], 'sources': [ '../../mojo/public/cpp/bindings/array.h', + '../../mojo/public/cpp/bindings/associated_binding.h', + '../../mojo/public/cpp/bindings/associated_group.h', + '../../mojo/public/cpp/bindings/associated_interface_ptr.h', + '../../mojo/public/cpp/bindings/associated_interface_ptr_info.h', + '../../mojo/public/cpp/bindings/associated_interface_request.h', '../../mojo/public/cpp/bindings/binding.h', '../../mojo/public/cpp/bindings/callback.h', '../../mojo/public/cpp/bindings/interface_ptr.h', @@ -104,6 +109,8 @@ '../../mojo/public/cpp/bindings/lib/array_internal.cc', '../../mojo/public/cpp/bindings/lib/array_internal.h', '../../mojo/public/cpp/bindings/lib/array_serialization.h', + '../../mojo/public/cpp/bindings/lib/associated_group.cc', + '../../mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h', '../../mojo/public/cpp/bindings/lib/bindings_internal.h', '../../mojo/public/cpp/bindings/lib/bindings_serialization.cc', '../../mojo/public/cpp/bindings/lib/bindings_serialization.h', @@ -369,6 +376,31 @@ 'mojo_cpp_bindings', ], }, + { + 'target_name': 'mojo_public_test_associated_interfaces_mojom', + 'type': 'none', + 'variables': { + # These files are not included in the mojo_public_test_interfaces_mojom + # target because associated interfaces are not supported by all bindings + # languages yet. + 'mojom_files': [ + '../../mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom', + ], + }, + 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], + }, + { + # GN version: //mojo/public/interfaces/bindings/tests:test_associated_interfaces + 'target_name': 'mojo_public_test_associated_interfaces', + 'type': 'static_library', + 'export_dependent_settings': [ + 'mojo_cpp_bindings', + ], + 'dependencies': [ + 'mojo_public_test_associated_interfaces_mojom', + 'mojo_cpp_bindings', + ], + }, ], 'conditions': [ ['OS == "android"', {
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.cc b/third_party/mojo/src/mojo/edk/embedder/embedder.cc index 8fcf6e0..95bfd8a 100644 --- a/third_party/mojo/src/mojo/edk/embedder/embedder.cc +++ b/third_party/mojo/src/mojo/edk/embedder/embedder.cc
@@ -13,7 +13,9 @@ #include "base/memory/scoped_ptr.h" #include "base/task_runner.h" #include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/process_delegate.h" +#include "mojo/edk/system/core.h" #include "third_party/mojo/src/mojo/edk/embedder/embedder_internal.h" #include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" #include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" @@ -27,8 +29,6 @@ #include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h" #include "third_party/mojo/src/mojo/edk/system/platform_handle_dispatcher.h" #include "third_party/mojo/src/mojo/edk/system/raw_channel.h" -#include "../../../../../../mojo/edk/system/core.h" -#include "../../../../../../mojo/edk/embedder/embedder_internal.h" namespace mojo { namespace embedder { @@ -94,6 +94,28 @@ } // namespace +#if defined(OS_WIN) +void PreInitializeParentProcess() { + edk::PreInitializeParentProcess(); +} + +void PreInitializeChildProcess() { + edk::PreInitializeChildProcess(); +} + +HANDLE ChildProcessLaunched(HANDLE child_process) { + return edk::ChildProcessLaunched(child_process); +} + +void ChildProcessLaunched(HANDLE child_process, HANDLE server_pipe) { + return edk::ChildProcessLaunched(child_process, server_pipe); +} + +void SetParentPipeHandle(HANDLE pipe) { + edk::SetParentPipeHandle(pipe); +} +#endif + void SetMaxMessageSize(size_t bytes) { system::GetMutableConfiguration()->max_message_num_bytes = bytes; // TODO(use_chrome_edk): also set this in the new EDK.
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.h b/third_party/mojo/src/mojo/edk/embedder/embedder.h index ba89481..2f2dfd2b 100644 --- a/third_party/mojo/src/mojo/edk/embedder/embedder.h +++ b/third_party/mojo/src/mojo/edk/embedder/embedder.h
@@ -19,10 +19,24 @@ #include "third_party/mojo/src/mojo/edk/system/system_impl_export.h" namespace mojo { +namespace edk { +class TokenSerializer; +} + namespace embedder { class ProcessDelegate; +#if defined(OS_WIN) +// Wrapper functions around the ones in src/mojo/edk for component builds. +MOJO_SYSTEM_IMPL_EXPORT void PreInitializeParentProcess(); +MOJO_SYSTEM_IMPL_EXPORT void PreInitializeChildProcess(); +MOJO_SYSTEM_IMPL_EXPORT HANDLE ChildProcessLaunched(HANDLE child_process); +MOJO_SYSTEM_IMPL_EXPORT void ChildProcessLaunched(HANDLE child_process, + HANDLE server_pipe); +MOJO_SYSTEM_IMPL_EXPORT void SetParentPipeHandle(HANDLE pipe); +#endif + // Basic configuration/initialization ------------------------------------------ // |Init()| sets up the basic Mojo system environment, making the |Mojo...()|
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/.bower.json index 4bf4a72b..a688498 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-a11y-keys-behavior", - "version": "1.0.8", + "version": "1.0.9", "description": "A behavior that enables keybindings for greater a11y.", "keywords": [ "web-components", @@ -26,15 +26,16 @@ "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/iron-a11y-keys-behavior", - "_release": "1.0.8", + "_release": "1.0.9", "_resolution": { "type": "version", - "tag": "v1.0.8", - "commit": "df29a9edcff3b4693707f1e3eebce5a1dc46e946" + "tag": "v1.0.9", + "commit": "63dd1ce94223ae6a226e653ef5a458a66c950e79" }, "_source": "git://github.com/PolymerElements/iron-a11y-keys-behavior.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/README.md b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/README.md index 2d16daa2..f527af9 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/README.md
@@ -1,5 +1,21 @@ -iron-a11y-keys-behavior -======================= + +<!--- + +This README is automatically generated from the comments in these files: +iron-a11y-keys-behavior.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-a11y-keys-behavior) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-a11y-keys-behavior)_ + + +##Polymer.IronA11yKeysBehavior + `Polymer.IronA11yKeysBehavior` provides a normalized interface for processing keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding). @@ -13,3 +29,5 @@ node. The `keys-pressed` event will fire when one of the key combinations set with the `keys` property is pressed. + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/bower.json index 623d471..40fbe1d 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-a11y-keys-behavior", - "version": "1.0.8", + "version": "1.0.9", "description": "A behavior that enables keybindings for greater a11y.", "keywords": [ "web-components", @@ -26,7 +26,8 @@ "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/.bower.json index b7650ad..4362023 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-a11y-keys", - "version": "1.0.3", + "version": "1.0.4", "description": "A basic element implementation of iron-a11y-keys-behavior, matching the legacy core-a11y-keys.", "keywords": [ "web-components", @@ -27,15 +27,16 @@ "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/iron-a11y-keys", - "_release": "1.0.3", + "_release": "1.0.4", "_resolution": { "type": "version", - "tag": "v1.0.3", - "commit": "823d3dd6a9688fefae8bd351b49667c0f01e1569" + "tag": "v1.0.4", + "commit": "51a34396a392bcfb45592900973c35eceb11f0d7" }, "_source": "git://github.com/PolymerElements/iron-a11y-keys.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/.travis.yml b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/.travis.yml deleted file mode 100644 index fc9f77f5..0000000 --- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: GYOQylogyw3LQdQ+65plW6DKXBklQm4M72U6UuaEu+e12QB7DGcWPhrDko7c7uc3DNVHFWzOw4r4DUAgMZM/7+ifTW6ARnXcu/FWfhVqRRjEpgSenMFo+QRjM5VmCuIqVlXV+tz+PXhBd9M/4TYOs8Tu+caCrSAD0SfLXV+FEZjqno6xYiZvW9xpvMWRE+hlDjV1JWEb6drxR8yhykDdByRQ1F0xbR/QzQXQe6fvDWTjwV7XIketFhfl5cQWESWJPhKMOf6DmJsoZojTpD3kcNlRGiC72SSlk5WukKdP2Bkt0MADxw4VyqoGWwXaIJxy+/bQe3nwZKCTlv+xGVRZyyqTeeHBjB9UDABq9KpJVBydAvrCoXYK+avUGsPE835hdoojwU8hbAAVLPFCRGvyXZ8Yvqq+FHnf2kb6iGakJOt4KA6GzaloBpj9FlZIcha/Q6iDQJ/Ec9YFwMVzutLAWok47u+QNWXe8TW7PPXleGhUjZID5bUKjKnKleHdVW05x/mXpmt1FYUuK7fD7klUEEg5lNtHO4WBBtmuns4iVv6BGgjjLuElqqzC1Lx69i0Bmh8bL5WV9n04/xJ701J+WATqdrGH2DyR2DwgCMbfHiQzyIQhpySTzcaYW9v87ZjojqZ5VAHO99JLPJVRfrm/Lh6RzDHq7Vn7azUoOcEnybM= - - secure: e+QHe/dcItz7qPotuYi2Pm1BlaEKIjTnUiUmB2KAu7nUzZD1sYwI29/XCX+cueDmlMibrWOnuZBrhG0/dyYU8oLDFu9F6E81K0jnNkhI4NXAPrwL58uEbsSKtf9FLYTWDRmik/vjarUEwdtx8kwCG6t9ynZLH1wiiLdJ/j+TGGRXxUePysIsAo/urEOEutnfsRR7E+tPE7hMbCZnHyJ9xYp/VbuXI7tvLoRrAfcIh19ZMCNKHlT2Gnl0jw5nlidNVm8zrMnl4ZTYa9mnqGvcZkVtZhAjcLPwUQ1xL/viXs0qj8u8hy135EpWoRcKJJviksMErIfBGreACsx+D5E3g5ZVrYdaFjx5f3MsjTpbyfC4/ZsqRFePkVLxS+hPZg9/HzwQI/v+YrTEpTWY5Xb/ZsMqCmAWNJGt1+c72dhLlRYb5Cb7UV6qqnYWNbgO12c3FZ9qPWnCteyFofqQt82OwU1osALBDGdKsmjiiWEzVxPoLe4C73dIiZdW84+6KZNECkN5zFBwKBzc7UuYFKWObQGc6KTSJccFXKaEqwmWXI/2qKTq8gvoXrRfZ4Bm8vFUuRxPgnl83CAMM7GE08+svHycPof1ZVEVNdo6cLw5dABqd2A1t2CCCJGTJyeL0w3wm4m8ZnK0HFY7z3TBIFUniD3UyDOWoF8gfo9R5evSoLM=
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/bower.json b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/bower.json index 00dc447..ca79f0a 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-a11y-keys", - "version": "1.0.3", + "version": "1.0.4", "description": "A basic element implementation of iron-a11y-keys-behavior, matching the legacy core-a11y-keys.", "keywords": [ "web-components", @@ -27,7 +27,8 @@ "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/.bower.json index e732fcc..81113ef0 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-autogrow-textarea", - "version": "1.0.8", + "version": "1.0.10", "description": "A textarea element that automatically grows with input", "authors": [ "The Polymer Authors" @@ -11,9 +11,7 @@ "input", "textarea" ], - "main": [ - "iron-autogrow-textarea.html" - ], + "main": "iron-autogrow-textarea.html", "private": true, "repository": { "type": "git", @@ -33,15 +31,15 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.8", + "_release": "1.0.10", "_resolution": { "type": "version", - "tag": "v1.0.8", - "commit": "ea7fb14d8038ccbedc6e85b9c4842b68c659a503" + "tag": "v1.0.10", + "commit": "1ba4f97e250dc14e9638d95be582dd62b9083736" }, "_source": "git://github.com/PolymerElements/iron-autogrow-textarea.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/README.md b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/README.md index 699b15ae..b0127f8 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/README.md
@@ -1,4 +1,21 @@ -# iron-autogrow-textarea + +<!--- + +This README is automatically generated from the comments in these files: +iron-autogrow-textarea.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-autogrow-textarea) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-autogrow-textarea)_ + + +##<iron-autogrow-textarea> + `iron-autogrow-textarea` is an element containing a textarea that grows in height as more lines of input are entered. Unless an explicit height or the `maxRows` property is set, it will @@ -9,4 +26,14 @@ <iron-autogrow-textarea></iron-autogrow-textarea> Because the `textarea`'s `value` property is not observable, you should use -this element's `bind-value` instead for imperative updates. \ No newline at end of file +this element's `bind-value` instead for imperative updates. + +### Styling + +The following custom properties and mixins are available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--iron-autogrow-textarea` | Mixin applied to the textarea | `{}` + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/bower.json b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/bower.json index 8fdbca8..61a9c49a 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-autogrow-textarea", - "version": "1.0.8", + "version": "1.0.10", "description": "A textarea element that automatically grows with input", "authors": [ "The Polymer Authors" @@ -11,9 +11,7 @@ "input", "textarea" ], - "main": [ - "iron-autogrow-textarea.html" - ], + "main": "iron-autogrow-textarea.html", "private": true, "repository": { "type": "git", @@ -33,7 +31,7 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html index c837d21..cdd80b2f 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html +++ b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html
@@ -25,7 +25,9 @@ this element's `bind-value` instead for imperative updates. ### Styling + The following custom properties and mixins are available for styling: + Custom property | Description | Default ----------------|-------------|---------- `--iron-autogrow-textarea` | Mixin applied to the textarea | `{}`
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-behaviors/.bower.json index 79061c0e..b5f528b 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-behaviors/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-behaviors", - "version": "1.0.10", + "version": "1.0.11", "description": "Provides a set of behaviors for the iron elements", "private": true, "authors": [ @@ -16,23 +16,25 @@ ], "license": "http://polymer.github.io/LICENSE.txt", "dependencies": { - "polymer": "Polymer/polymer#^1.0.0", + "polymer": "Polymer/polymer#^1.2.0", "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0" }, "devDependencies": { "paper-styles": "polymerelements/paper-styles#^1.0.2", + "paper-input": "polymerelements/paper-input#^1.0.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0", "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/iron-behaviors", - "_release": "1.0.10", + "_release": "1.0.11", "_resolution": { "type": "version", - "tag": "v1.0.10", - "commit": "da937a6c5841fc9dba57f3087083445c9ad709a8" + "tag": "v1.0.11", + "commit": "084fbc7f60343d717bb2208f350774f4c9899777" }, "_source": "git://github.com/PolymerElements/iron-behaviors.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/.travis.yml b/third_party/polymer/v1_0/components-chromium/iron-behaviors/.travis.yml deleted file mode 100644 index e873af2..0000000 --- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/.travis.yml +++ /dev/null
@@ -1,30 +0,0 @@ -language: node_js -sudo: false -cache: - directories: - - node_modules -matrix: - include: - - node_js: stable - script: xvfb-run -a wct --simpleOutput -l firefox -l chrome - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct --simpleOutput -s 'Windows 10/microsoftedge' -s 'Windows 8.1/internet explorer@11' -s 'Windows 7/internet explorer@10' -s 'OS X 10.10/safari@8' -s 'OS X 10.9/safari@7' - fi -before_script: -- npm install bower web-component-tester -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: ZOqj2XVNVwfT74rHxg/ljcAsS6FnmDpRSsXbsy1Icv9DcLHrMlmyQ10gWBjE/YXYF0Uv4akQ1qqn0TJaKOtp9HZeH+P6OPAYk2vJbWD7qp52pPtIqEFomcsUyflt4IjfaXKuN4FMod7PSWVSGJ+DxSguJvZKILkrs5d/rJdFv3c= - - secure: clkqemGQG16TXyAPkv9LBv6x3SbT3ZM0eo8LETx4uNKi3WzlwgXxZA9b5Sr5wYzxyxFFpnhDXW7CL4+UjYu1atGNeTW2TuSaYUPHtgu67OFDr8Jbw047p1XQb5enPSt9+YxrHKfjHBiJvWulJ8rCSQshU9Rhe0DC6NrFRPFgk0A=
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json b/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json index e001c7f..507f2924 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-behaviors", - "version": "1.0.10", + "version": "1.0.11", "description": "Provides a set of behaviors for the iron elements", "private": true, "authors": [ @@ -16,15 +16,17 @@ ], "license": "http://polymer.github.io/LICENSE.txt", "dependencies": { - "polymer": "Polymer/polymer#^1.0.0", + "polymer": "Polymer/polymer#^1.2.0", "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0" }, "devDependencies": { "paper-styles": "polymerelements/paper-styles#^1.0.2", + "paper-input": "polymerelements/paper-input#^1.0.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0", "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js index 936987f..d7653a9 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js
@@ -120,14 +120,6 @@ this._setPressed(false); }, - __isFocusedLightDescendant: function(target) { - var root = Polymer.dom(this).getOwnerRoot() || document; - var focusedElement = root.activeElement; - - // TODO(noms): remove the `this !== target` check once polymer#2610 is fixed. - return this !== target && this.isLightDescendant(target) && target == focusedElement; - }, - /** * @param {!KeyboardEvent} event . */ @@ -137,7 +129,7 @@ // Ignore the event if this is coming from a focused light child, since that // element will deal with it. - if (this.__isFocusedLightDescendant(target)) + if (this.isLightDescendant(target)) return; keyboardEvent.preventDefault(); @@ -154,7 +146,7 @@ // Ignore the event if this is coming from a focused light child, since that // element will deal with it. - if (this.__isFocusedLightDescendant(target)) + if (this.isLightDescendant(target)) return; if (this.pressed) {
diff --git a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/.bower.json index 91392b16..f67dfa0c 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-checked-element-behavior", - "version": "1.0.2", + "version": "1.0.3", "description": "Implements an element that has a checked attribute and can be added to a form", "authors": "The Polymer Authors", "keywords": [ @@ -9,9 +9,7 @@ "iron", "behavior" ], - "main": [ - "iron-checked-element-behavior.html" - ], + "main": "iron-checked-element-behavior.html", "private": true, "repository": { "type": "git", @@ -33,11 +31,11 @@ "web-component-tester": "*", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.2", + "_release": "1.0.3", "_resolution": { "type": "version", - "tag": "v1.0.2", - "commit": "975b9f22ebd89ef457491fcc44cb86b660fc42cd" + "tag": "v1.0.3", + "commit": "5a0520d20eb8883076ce64117f2726ba209ebc97" }, "_source": "git://github.com/PolymerElements/iron-checked-element-behavior.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/README.md b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/README.md index b892ad0..fc570916 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/README.md
@@ -1,2 +1,25 @@ -# iron-checked-element-behavior -Implements an element that has a checked attribute and can be added to a form + +<!--- + +This README is automatically generated from the comments in these files: +iron-checked-element-behavior.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-checked-element-behavior) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-checked-element-behavior)_ + + +##Polymer.IronCheckedElementBehavior + + +Use `Polymer.IronCheckedElementBehavior` to implement a custom element +that has a `checked` property, which can be used for validation if the +element is also `required`. Element instances implementing this behavior +will also be registered for use in an `iron-form` element. + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json index fd78387..b29aa54 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-checked-element-behavior", - "version": "1.0.2", + "version": "1.0.3", "description": "Implements an element that has a checked attribute and can be added to a form", "authors": "The Polymer Authors", "keywords": [ @@ -9,9 +9,7 @@ "iron", "behavior" ], - "main": [ - "iron-checked-element-behavior.html" - ], + "main": "iron-checked-element-behavior.html", "private": true, "repository": { "type": "git",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/iron-checked-element-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/iron-checked-element-behavior-extracted.js index 17cc73d4..101506ee 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/iron-checked-element-behavior-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/iron-checked-element-behavior-extracted.js
@@ -40,7 +40,8 @@ /* Overriden from Polymer.IronFormElementBehavior */ value: { type: String, - value: '' + value: 'on', + observer: '_valueChanged' } }, @@ -48,6 +49,13 @@ '_requiredChanged(required)' ], + created: function() { + // Used by `iron-form` to handle the case that an element with this behavior + // doesn't have a role of 'checkbox' or 'radio', but should still only be + // included when the form is serialized if `this.checked === true`. + this._hasIronCheckedElementBehavior = true; + }, + /** * Returns false if the element is required and not checked, and true otherwise. * @return {boolean} true if `required` is false, or if `required` and `checked` are both true. @@ -68,15 +76,20 @@ }, /** - * Update the element's value when checked. + * Fire `iron-changed` when the checked state changes. */ _checkedChanged: function() { this.active = this.checked; - // Unless the user has specified a value, a checked element has the - // default value "on" when checked. - if (this.value === '') - this.value = this.checked ? 'on' : ''; this.fire('iron-change'); + }, + + /** + * Reset value to 'on' if it is set to `undefined`. + */ + _valueChanged: function() { + if (this.value === undefined || this.value === null) { + this.value = 'on'; + } } };
diff --git a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/.bower.json index fe5067c..b33aab0 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-fit-behavior", - "version": "1.0.4", + "version": "1.0.5", "license": "http://polymer.github.io/LICENSE.txt", "description": "Fits an element inside another element", "private": true, @@ -24,15 +24,16 @@ "paper-styles": "polymerelements/paper-styles#^1.0.2", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/iron-fit-behavior", - "_release": "1.0.4", + "_release": "1.0.5", "_resolution": { "type": "version", - "tag": "v1.0.4", - "commit": "db76c6b9f3df86ee6dfc2339975313ac2efc6474" + "tag": "v1.0.5", + "commit": "18dec1eb5c7217be4d360c0fb9101fe899136f92" }, "_source": "git://github.com/PolymerElements/iron-fit-behavior.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/README.md b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/README.md index 8f4fc763..d8ac001 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/README.md
@@ -1,3 +1,34 @@ -# iron-fit-behavior -Fits an element in the window, or another element. +<!--- + +This README is automatically generated from the comments in these files: +iron-fit-behavior.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-fit-behavior) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-fit-behavior)_ + + +##Polymer.IronFitBehavior + + +Polymer.IronFitBehavior fits an element in another element using `max-height` and `max-width`, and +optionally centers it in the window or another element. + +The element will only be sized and/or positioned if it has not already been sized and/or positioned +by CSS. + +CSS properties | Action +-----------------------------|------------------------------------------- +`position` set | Element is not centered horizontally or vertically +`top` or `bottom` set | Element is not vertically centered +`left` or `right` set | Element is not horizontally centered +`max-height` or `height` set | Element respects `max-height` or `height` +`max-width` or `width` set | Element respects `max-width` or `width` + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/bower.json index f795545..7e0c31d7 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-fit-behavior", - "version": "1.0.4", + "version": "1.0.5", "license": "http://polymer.github.io/LICENSE.txt", "description": "Fits an element inside another element", "private": true, @@ -24,7 +24,8 @@ "paper-styles": "polymerelements/paper-styles#^1.0.2", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/.bower.json index 49f7c426..ffb51f3 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-flex-layout", - "version": "1.0.5", + "version": "1.2.0", "description": "Provide flexbox-based layouts", "keywords": [ "web-components", @@ -18,7 +18,7 @@ "url": "git://github.com/PolymerElements/iron-flex-layout.git" }, "dependencies": { - "polymer": "Polymer/polymer#^1.0.0" + "polymer": "Polymer/polymer#^1.1.0" }, "devDependencies": { "paper-styles": "polymerelements/paper-styles#^1.0.0", @@ -28,11 +28,11 @@ "iron-component-page": "polymerelements/iron-component-page#^1.0.0" }, "homepage": "https://github.com/PolymerElements/iron-flex-layout", - "_release": "1.0.5", + "_release": "1.2.0", "_resolution": { "type": "version", - "tag": "v1.0.5", - "commit": "00daa8acc95fe53d7cbbe5f9059241c4648ff22e" + "tag": "v1.2.0", + "commit": "4bf53ba623140d0d2663a404e91ee45b96299118" }, "_source": "git://github.com/PolymerElements/iron-flex-layout.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/.travis.yml b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/.travis.yml deleted file mode 100644 index b3f20a9..0000000 --- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: jFaXkmco40NlJT4VyFYM34Zv9D1XVfLXgixobnyHQyJDBKSXrNLcwDuvrGUpJx/pwBCxEhKAbvxeJ+PBMUv8QV08MAdw2S6QOsIe3CUxAehoNoOMJw5duhE8faWlz8qzmCWEowHVFUeVsd0ZUsgOu6RTspj2A51D/CztQuW0Ljw= - - secure: fKrO5yMx8kZM1WQ3k0bzo6MCREKGW2WkCl2suDjuEtb1SQ/SaZa9Tun0fcqIHVJqg9+jOS1Romt/+MN27Nc6IT1tv/NdLd+uWjtMA+OzLyv48gzcdu8Ls/TISUGm5Wb7XHkcvMAb1tRoBs5BOvQ/85FilZLEq1km8snG9ZsOOWI=
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/bower.json b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/bower.json index da26e31..c9737e3 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-flex-layout", - "version": "1.0.5", + "version": "1.2.0", "description": "Provide flexbox-based layouts", "keywords": [ "web-components", @@ -18,7 +18,7 @@ "url": "git://github.com/PolymerElements/iron-flex-layout.git" }, "dependencies": { - "polymer": "Polymer/polymer#^1.0.0" + "polymer": "Polymer/polymer#^1.1.0" }, "devDependencies": { "paper-styles": "polymerelements/paper-styles#^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-shadow-flex-layout.html b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-shadow-flex-layout.html index c42067af5..fe55ec8 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-shadow-flex-layout.html +++ b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-shadow-flex-layout.html
@@ -284,7 +284,7 @@ html /deep/ .fixed-right { top: 0; right: 0; - botttom: 0; + bottom: 0; } html /deep/ .fixed-bottom { @@ -295,7 +295,7 @@ html /deep/ .fixed-left { top: 0; - botttom: 0; + bottom: 0; left: 0; }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/index.html b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/index.html index 03ae3fb..7d3b088 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/index.html +++ b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/index.html
@@ -2,11 +2,11 @@ <!-- @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 +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 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <html> <head>
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html index c937958..b55ef02 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html +++ b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html
@@ -295,6 +295,11 @@ overflow: auto; }; + --layout-fullbleed: { + margin: 0; + height: 100vh; + } + /* fixed position */ --layout-fixed-top: {
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icons/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-icons/.bower.json index 0186178..93533ec 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-icons/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-icons/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-icons", - "version": "1.0.4", + "version": "1.0.5", "description": "A set of icons for use with iron-icon", "authors": [ "The Polymer Authors" @@ -34,11 +34,11 @@ "util", "update-icons.sh" ], - "_release": "1.0.4", + "_release": "1.0.5", "_resolution": { "type": "version", - "tag": "v1.0.4", - "commit": "1a54850a7196eb8d9d7ec1c4dea064972b7bfd4c" + "tag": "v1.0.5", + "commit": "39da54afbc17af343d1f95e62c5c0c477492677a" }, "_source": "git://github.com/PolymerElements/iron-icons.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icons/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-icons/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-icons/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icons/README.md b/third_party/polymer/v1_0/components-chromium/iron-icons/README.md index 5502532bc..974ddf93 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-icons/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-icons/README.md
@@ -1,6 +1,39 @@ -iron-icons -========= -## 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. +<!--- + +This README is automatically generated from the comments in these files: +iron-icons.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-icons) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-icons)_ + + +##<iron-icons> + + +`iron-icons` is a utility 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. + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icons/bower.json b/third_party/polymer/v1_0/components-chromium/iron-icons/bower.json index 732bbc1..5b2e93ff 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-icons/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-icons/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-icons", - "version": "1.0.4", + "version": "1.0.5", "description": "A set of icons for use with iron-icon", "authors": [ "The Polymer Authors"
diff --git a/third_party/polymer/v1_0/components-chromium/iron-iconset-svg/.travis.yml b/third_party/polymer/v1_0/components-chromium/iron-iconset-svg/.travis.yml deleted file mode 100644 index d4e78c4..0000000 --- a/third_party/polymer/v1_0/components-chromium/iron-iconset-svg/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: UR1rxThVZH+l6fFHhAlgNIWs9wHmC5A102oAQBtCuQqKiXPZCDAPQHdjufX8z6hH93JkR+Esh2VPv0baSXFrHteKTRN6bsNDTMFDdHJ5BiRAdhVoV6bsdNH2GTgRXQ+ACMgrh4sXLA5+2Z+JGq7m0zaHehDfNZqmo/1U59qImP8= - - secure: PmWDypBdjKlUGPn9UoBEkjoYiyJFQGe2QiACmdOgueOLSLeA6xW+/1521uFIBHpwuWn29mxVYv5gS1D8hafWhZdXn4OYQl550RrT092jXIO6+mMKZXPmUaKCkPMY6QYJJ5j9ZOC36KgF//IpoE7OCxpLReYOD2KBR3mhw0jOYJA=
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-input/.bower.json index a362e37a..a0bd5a4 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-input/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-input/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-input", - "version": "1.0.6", + "version": "1.0.7", "description": "An input element with data binding", "authors": [ "The Polymer Authors" @@ -10,9 +10,7 @@ "polymer", "input" ], - "main": [ - "iron-input.html" - ], + "main": "iron-input.html", "private": true, "repository": { "type": "git", @@ -30,14 +28,14 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.6", + "_release": "1.0.7", "_resolution": { "type": "version", - "tag": "v1.0.6", - "commit": "a206c6140aad96d5355074676713f9e0a1b1581d" + "tag": "v1.0.7", + "commit": "7ba38f9121694d72b7390567cb91b6ac18141d2b" }, "_source": "git://github.com/PolymerElements/iron-input.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-input/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-input/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/README.md b/third_party/polymer/v1_0/components-chromium/iron-input/README.md index 05a74b72..70a74e9 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-input/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-input/README.md
@@ -1,16 +1,49 @@ -# iron-input -An input with data binding. +<!--- + +This README is automatically generated from the comments in these files: +iron-input.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-input) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-input)_ + + +##<iron-input> + + +`<iron-input>` adds two-way binding and custom validators using `Polymer.IronValidatorBehavior` +to `<input>`. + +### Two-way binding By default you can only get notified of changes to an `input`'s `value` due to user input: -```html -<input value="{{myValue::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. -```html -<input is="iron-input" bind-value="{{myValue}}"> -``` + <input is="iron-input" bind-value="{{myValue}}"> + +### Custom validators + +You can use custom validators that implement `Polymer.IronValidatorBehavior` with `<iron-input>`. + + <input is="iron-input" validator="my-custom-validator"> + +### Stopping invalid input + +It may be desirable to only allow users to enter certain characters. You can use the +`prevent-invalid-input` and `allowed-pattern` attributes together to accomplish this. This feature +is separate from validation, and `allowed-pattern` does not affect how the input is validated. + + <!-- only allow characters that match [0-9] --> + <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]"> + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/bower.json b/third_party/polymer/v1_0/components-chromium/iron-input/bower.json index 79481b1..5705f6a 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-input/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-input/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-input", - "version": "1.0.6", + "version": "1.0.7", "description": "An input element with data binding", "authors": [ "The Polymer Authors" @@ -10,9 +10,7 @@ "polymer", "input" ], - "main": [ - "iron-input.html" - ], + "main": "iron-input.html", "private": true, "repository": { "type": "git", @@ -30,7 +28,7 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js index c72907b..8021742 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js
@@ -65,7 +65,8 @@ * Regular expression to match valid input characters. */ allowedPattern: { - type: String + type: String, + observer: "_allowedPatternChanged" }, _previousValidInput: { @@ -116,6 +117,11 @@ this.fire('bind-value-changed', {value: this.bindValue}); }, + _allowedPatternChanged: function() { + // Force to prevent invalid input when an `allowed-pattern` is set + this.preventInvalidInput = this.allowedPattern ? true : false; + }, + _onInput: function() { // Need to validate each of the characters pasted if they haven't // been validated inside `_onKeypress` already.
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-list/.bower.json index c5159e5..7076e9d 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-list/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-list/.bower.json
@@ -7,7 +7,7 @@ "list", "virtual-list" ], - "version": "1.1.5", + "version": "1.1.6", "homepage": "https://github.com/PolymerElements/iron-list", "authors": [ "The Polymer Authors" @@ -37,11 +37,11 @@ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.2", "web-component-tester": "*" }, - "_release": "1.1.5", + "_release": "1.1.6", "_resolution": { "type": "version", - "tag": "v1.1.5", - "commit": "c6bf7caf1745cc3bed0769d41ac405476ef981b8" + "tag": "v1.1.6", + "commit": "41ba08e96ffb62ce9f0f5f50ddd41aee8e8b10b2" }, "_source": "git://github.com/PolymerElements/iron-list.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-list/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-list/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/README.md b/third_party/polymer/v1_0/components-chromium/iron-list/README.md index caf6819..1b31769 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-list/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-list/README.md
@@ -1,7 +1,24 @@ -iron-list -======================== -`iron-list` displays a virtual, *'infinite'* list. The template inside +<!--- + +This README is automatically generated from the comments in these files: +iron-list.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-list) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-list)_ + + +##<iron-list> + + + +`iron-list` displays a virtual, 'infinite' list. The template inside the iron-list element represents the DOM to create for each list item. The `items` property specifies an array of list item data. @@ -13,7 +30,7 @@ as the result of a user interaction with the list item must be bound to the model to avoid view state inconsistency. -__Important:__ `iron-list` must ether be explicitly sized, or delegate scrolling to an +__Important:__ `iron-list` must either be explicitly sized, or delegate scrolling to an explicitly sized parent. By "explicitly sized", we mean it either has an explicit CSS `height` property set via a class or inline style, or else is sized by other layout means (e.g. the `flex` or `fit` classes). @@ -22,14 +39,12 @@ List item templates should bind to template models of the following structure: -```js -{ - index: 0, // data index for this item - item: { // user data corresponding to items[index] - /* user item data */ - } -} -``` + { + index: 0, // data index for this item + item: { // user data corresponding to items[index] + /* user item data */ + } + } Alternatively, you can change the property name used as data index by changing the `indexAs` property. The `as` property defines the name of the variable to add to the binding @@ -63,20 +78,6 @@ </template> ``` -### Resizing - -`iron-list` lays out the items when it recives a notification via the `iron-resize` event. -This event is fired by any element that implements `IronResizableBehavior`. - -By default, elements such as `iron-pages`, `paper-tabs` or `paper-dialog` will trigger -this event automatically. If you hide the list manually (e.g. you use `display: none`) -you might want to implement `IronResizableBehavior` or fire this event manually right -after the list became visible again. e.g. - -```js -document.querySelector('iron-list').fire('iron-resize'); -``` - ### Styling Use the `--iron-list-items-container` mixin to style the container of items, e.g. @@ -89,8 +90,30 @@ } ``` +### Resizing + +`iron-list` lays out the items when it receives a notification via the `iron-resize` event. +This event is fired by any element that implements `IronResizableBehavior`. + +By default, elements such as `iron-pages`, `paper-tabs` or `paper-dialog` will trigger +this event automatically. If you hide the list manually (e.g. you use `display: none`) +you might want to implement `IronResizableBehavior` or fire this event manually right +after the list became visible again. e.g. + +```js +document.querySelector('iron-list').fire('iron-resize'); +``` + ### When should `<iron-list>` be used? -`iron-list` should be used when a page has significantly more DOM nodes than the ones visible on the screen. e.g. the page has 500 nodes, but only 20 are visible at the time. This is why we refer to it as a `virtual` list. In this case, a `dom-repeat` will still create 500 nodes which could slow down the web app, but `iron-list` will only create 20. +`iron-list` should be used when a page has significantly more DOM nodes than the ones +visible on the screen. e.g. the page has 500 nodes, but only 20 are visible at the time. +This is why we refer to it as a `virtual` list. In this case, a `dom-repeat` will still +create 500 nodes which could slow down the web app, but `iron-list` will only create 20. -However, having an `iron-list` does not mean that you can load all the data at once. Say, you have a million records in the database, you want to split the data into pages so you can bring a page at the time. The page could contain 500 items, and iron-list will only render 20. +However, having an `iron-list` does not mean that you can load all the data at once. +Say, you have a million records in the database, you want to split the data into pages +so you can bring a page at the time. The page could contain 500 items, and iron-list +will only render 20. + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/bower.json b/third_party/polymer/v1_0/components-chromium/iron-list/bower.json index 3684260..1dfaa97 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-list/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-list/bower.json
@@ -7,7 +7,7 @@ "list", "virtual-list" ], - "version": "1.1.5", + "version": "1.1.6", "homepage": "https://github.com/PolymerElements/iron-list", "authors": [ "The Polymer Authors"
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js index df280d5..a7c75b8 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js
@@ -2,7 +2,7 @@ var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; - var DEFAULT_PHYSICAL_COUNT = 20; + var DEFAULT_PHYSICAL_COUNT = 3; var MAX_PHYSICAL_COUNT = 500; Polymer({ @@ -185,7 +185,7 @@ _scrollHeight: 0, /** - * The size of the viewport + * The height of the list. This is referred as the viewport in the context of list. */ _viewportSize: 0, @@ -221,6 +221,16 @@ _itemsRendered: false, /** + * The page that is currently rendered. + */ + _lastPage: null, + + /** + * The max number of pages to render. One page is equivalent to the height of the list. + */ + _maxPages: 3, + + /** * The bottom of the physical content. */ get _physicalBottom() { @@ -292,7 +302,7 @@ * to a viewport of physical items above and below the user's viewport. */ get _optPhysicalSize() { - return this._viewportSize * 3; + return this._viewportSize * this._maxPages; }, /** @@ -393,7 +403,7 @@ // IE 10|11 scrollTop may go above `_maxScrollTop` // iOS `scrollTop` may go below 0 and above `_maxScrollTop` var scrollTop = Math.max(0, Math.min(this._maxScrollTop, this._scroller.scrollTop)); - var tileHeight, tileTop, kth, recycledTileSet, scrollBottom; + var tileHeight, tileTop, kth, recycledTileSet, scrollBottom, physicalBottom; var ratio = this._ratio; var delta = scrollTop - this._scrollPosition; var recycledTiles = 0; @@ -408,6 +418,7 @@ this._firstVisibleIndexVal = null; scrollBottom = this._scrollBottom; + physicalBottom = this._physicalBottom; // random access if (Math.abs(delta) > this._physicalSize) { @@ -418,7 +429,6 @@ else if (delta < 0) { var topSpace = scrollTop - this._physicalTop; var virtualStart = this._virtualStart; - var physicalBottom = this._physicalBottom; recycledTileSet = []; @@ -450,7 +460,7 @@ } // scroll down else if (delta > 0) { - var bottomSpace = this._physicalBottom - scrollBottom; + var bottomSpace = physicalBottom - scrollBottom; var virtualEnd = this._virtualEnd; var lastVirtualItemIndex = this._virtualCount-1; @@ -485,9 +495,8 @@ // If the list ever reach this case, the physical average is not significant enough // to create all the items needed to cover the entire viewport. // e.g. A few items have a height that differs from the average by serveral order of magnitude. - if (this._increasePoolIfNeeded()) { - // yield and set models to the new items - this.async(this._update); + if (physicalBottom < scrollBottom || this._physicalTop > scrollTop) { + this.async(this._increasePool.bind(this, 1)); } } else { this._virtualStart = this._virtualStart + recycledTiles; @@ -519,11 +528,8 @@ // set the scroller size this._updateScrollerSize(); - // increase the pool of physical items if needed - if (this._increasePoolIfNeeded()) { - // yield set models to the new items - this.async(this._update); - } + // increase the pool of physical items + this._increasePoolIfNeeded(); }, /** @@ -536,7 +542,6 @@ for (var i = 0; i < size; i++) { var inst = this.stamp(null); - // First element child is item; Safari doesn't support children[0] // on a doc fragment physicalItems[i] = inst.root.querySelector('*'); @@ -549,20 +554,25 @@ /** * Increases the pool of physical items only if needed. * This function will allocate additional physical items - * (limited by `MAX_PHYSICAL_COUNT`) if the content size is shorter than - * `_optPhysicalSize` - * - * @return boolean + * if the physical size is shorter than `_optPhysicalSize` */ _increasePoolIfNeeded: function() { - if (this._physicalAverage === 0) { - return false; - } - if (this._physicalBottom < this._scrollBottom || this._physicalTop > this._scrollPosition) { - return this._increasePool(1); - } - if (this._physicalSize < this._optPhysicalSize) { - return this._increasePool(Math.round((this._optPhysicalSize - this._physicalSize) * 1.2 / this._physicalAverage)); + if (this._viewportSize !== 0 && this._physicalSize < this._optPhysicalSize) { + // 0 <= `currentPage` <= `_maxPages` + var currentPage = Math.floor(this._physicalSize / this._viewportSize); + + if (currentPage === 0) { + // fill the first page + this.async(this._increasePool.bind(this, Math.round(this._physicalCount * 0.5))); + } else if (this._lastPage !== currentPage) { + // once a page is filled up, paint it and defer the next increase + requestAnimationFrame(this._increasePool.bind(this, 1)); + } else { + // fill the rest of the pages + this.async(this._increasePool.bind(this, 1)); + } + this._lastPage = currentPage; + return true; } return false; }, @@ -577,20 +587,17 @@ this._virtualCount, MAX_PHYSICAL_COUNT ); - var prevPhysicalCount = this._physicalCount; var delta = nextPhysicalCount - prevPhysicalCount; - if (delta <= 0) { - return false; + if (delta > 0) { + [].push.apply(this._physicalItems, this._createPool(delta)); + [].push.apply(this._physicalSizes, new Array(delta)); + + this._physicalCount = prevPhysicalCount + delta; + // tail call + return this._update(); } - - [].push.apply(this._physicalItems, this._createPool(delta)); - [].push.apply(this._physicalSizes, new Array(delta)); - - this._physicalCount = prevPhysicalCount + delta; - - return true; }, /** @@ -600,7 +607,8 @@ _render: function() { var requiresUpdate = this._virtualCount > 0 || this._physicalCount > 0; - if (this.isAttached && !this._itemsRendered && this._isVisible && requiresUpdate) { + if (this.isAttached && !this._itemsRendered && this._isVisible && requiresUpdate) { + this._lastPage = 0; this._update(); this._itemsRendered = true; } @@ -964,7 +972,7 @@ var hiddenContentSize = this._hiddenContentSize; // scroll to the item as much as we can - while (currentVirtualItem !== idx && targetOffsetTop < hiddenContentSize) { + while (currentVirtualItem < idx && targetOffsetTop < hiddenContentSize) { targetOffsetTop = targetOffsetTop + this._physicalSizes[currentTopItem]; currentTopItem = (currentTopItem + 1) % this._physicalCount; currentVirtualItem++; @@ -980,10 +988,8 @@ this._resetScrollPosition(this._physicalTop + targetOffsetTop + 1); // increase the pool of physical items if needed - if (this._increasePoolIfNeeded()) { - // yield set models to the new items - this.async(this._update); - } + this._increasePoolIfNeeded(); + // clear cached visible index this._firstVisibleIndexVal = null; },
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list.html b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list.html index 3684aba84..9b3148a 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list.html +++ b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list.html
@@ -23,7 +23,7 @@ as the result of a user interaction with the list item must be bound to the model to avoid view state inconsistency. -__Important:__ `iron-list` must ether be explicitly sized, or delegate scrolling to an +__Important:__ `iron-list` must either be explicitly sized, or delegate scrolling to an explicitly sized parent. By "explicitly sized", we mean it either has an explicit CSS `height` property set via a class or inline style, or else is sized by other layout means (e.g. the `flex` or `fit` classes). @@ -47,39 +47,45 @@ ##### data.json - [ - {"name": "Bob"}, - {"name": "Tim"}, - {"name": "Mike"} - ] +```js +[ + {"name": "Bob"}, + {"name": "Tim"}, + {"name": "Mike"} +] +``` The following code would render the list (note the name and checked properties are bound from the model object provided to the template scope): - <template is="dom-bind"> - <iron-ajax url="data.json" last-response="{{data}}" auto></iron-ajax> - <iron-list items="[[data]]" as="item"> - <template> - <div> - Name: <span>[[item.name]]</span> - </div> - </template> - </iron-list> +```html +<template is="dom-bind"> + <iron-ajax url="data.json" last-response="{{data}}" auto></iron-ajax> + <iron-list items="[[data]]" as="item"> + <template> + <div> + Name: <span>[[item.name]]</span> + </div> </template> + </iron-list> +</template> +``` ### Styling Use the `--iron-list-items-container` mixin to style the container of items, e.g. - iron-list { - --iron-list-items-container: { - margin: auto; - }; - } +```css +iron-list { + --iron-list-items-container: { + margin: auto; + }; +} +``` ### Resizing -`iron-list` lays out the items when it recives a notification via the `iron-resize` event. +`iron-list` lays out the items when it receives a notification via the `iron-resize` event. This event is fired by any element that implements `IronResizableBehavior`. By default, elements such as `iron-pages`, `paper-tabs` or `paper-dialog` will trigger @@ -87,8 +93,21 @@ you might want to implement `IronResizableBehavior` or fire this event manually right after the list became visible again. e.g. - document.querySelector('iron-list').fire('iron-resize'); +```js +document.querySelector('iron-list').fire('iron-resize'); +``` +### When should `<iron-list>` be used? + +`iron-list` should be used when a page has significantly more DOM nodes than the ones +visible on the screen. e.g. the page has 500 nodes, but only 20 are visible at the time. +This is why we refer to it as a `virtual` list. In this case, a `dom-repeat` will still +create 500 nodes which could slow down the web app, but `iron-list` will only create 20. + +However, having an `iron-list` does not mean that you can load all the data at once. +Say, you have a million records in the database, you want to split the data into pages +so you can bring a page at the time. The page could contain 500 items, and iron-list +will only render 20. @group Iron Element @element iron-list
diff --git a/third_party/polymer/v1_0/components-chromium/iron-media-query/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-media-query/.bower.json index 3cd0a8b..545011f1 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-media-query/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-media-query/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-media-query", - "version": "1.0.6", + "version": "1.0.7", "description": "Lets you bind to a CSS media query", "authors": [ "The Polymer Authors" @@ -23,17 +23,17 @@ }, "devDependencies": { "paper-styles": "polymerelements/paper-styles#^1.0.2", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, "main": "iron-media-query.html", - "_release": "1.0.6", + "_release": "1.0.7", "_resolution": { "type": "version", - "tag": "v1.0.6", - "commit": "fda20cb8e3bb2b49c2473b8a41fd2afae51db468" + "tag": "v1.0.7", + "commit": "a78cdbadb6de48857d176b964ab906a12872f2d3" }, "_source": "git://github.com/PolymerElements/iron-media-query.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-media-query/.travis.yml b/third_party/polymer/v1_0/components-chromium/iron-media-query/.travis.yml deleted file mode 100644 index 709938d..0000000 --- a/third_party/polymer/v1_0/components-chromium/iron-media-query/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: My9uxlkp4fZwSHKqo1RUv4yBhNl46XfbaiOsOStqJdI9l7hBfudSl7V2OZeLuV2pEDJC1z1ZqVU6C/K0/iTf7i66cd9g0iH5N+1qex8p2AcuP1evPWbwLw8moHH+M5E14MMXD8sPX4KauS8azmgRm61pppD5ZgKfCaeGZg7Tczs= - - secure: LgnZP4BNGBkTZhf8Vr7r9LdrOwq2/58TqqYkFFloEGBRT6HmumNSRwNbIwOh1U9jSTVkqjC2rn4G27u4XlEIs+QTD2PVSSEKy7Vbn0KxSNCvCGaOB1ZaxWTwZa7nkg09ZFRCHGh+WIbuV+BxyzsjOqlN82GSzFNSb3rxhqDM6dU=
diff --git a/third_party/polymer/v1_0/components-chromium/iron-media-query/bower.json b/third_party/polymer/v1_0/components-chromium/iron-media-query/bower.json index 044bf5f..9b2f3ae5 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-media-query/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-media-query/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-media-query", - "version": "1.0.6", + "version": "1.0.7", "description": "Lets you bind to a CSS media query", "authors": [ "The Polymer Authors" @@ -23,7 +23,7 @@ }, "devDependencies": { "paper-styles": "polymerelements/paper-styles#^1.0.2", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
diff --git a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/.bower.json index d1c161c..3b786a2 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-menu-behavior", - "version": "1.0.5", + "version": "1.0.6", "description": "Provides accessible menu behavior", "authors": "The Polymer Authors", "keywords": [ @@ -30,14 +30,14 @@ "paper-styles": "polymerelements/paper-styles#^1.0.2", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.5", + "_release": "1.0.6", "_resolution": { "type": "version", - "tag": "v1.0.5", - "commit": "f06af97a224fcb2098f4a0229ec2500350d4ccf0" + "tag": "v1.0.6", + "commit": "50f4e753b147ab397d81f64f4b2db962c43c4057" }, "_source": "git://github.com/PolymerElements/iron-menu-behavior.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/README.md b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/README.md index 42ab7fa..f751514 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/README.md
@@ -1,3 +1,29 @@ -# iron-menu-behavior + +<!--- + +This README is automatically generated from the comments in these files: +iron-menu-behavior.html iron-menubar-behavior.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-menu-behavior) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-menu-behavior)_ + + +##Polymer.IronMenuBehavior + `Polymer.IronMenuBehavior` implements accessible menu behavior. + + + +##Polymer.IronMenubarBehavior + + +`Polymer.IronMenubarBehavior` implements accessible menubar behavior. + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/bower.json index 66ad1b7..a250e54 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-menu-behavior", - "version": "1.0.5", + "version": "1.0.6", "description": "Provides accessible menu behavior", "authors": "The Polymer Authors", "keywords": [ @@ -30,7 +30,7 @@ "paper-styles": "polymerelements/paper-styles#^1.0.2", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-meta/.travis.yml b/third_party/polymer/v1_0/components-chromium/iron-meta/.travis.yml deleted file mode 100644 index fd27446b..0000000 --- a/third_party/polymer/v1_0/components-chromium/iron-meta/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: eGcuDAJt+1GPrC6u95vHufjnSXWbVBZpW7oKQhZjcHrN19l9COdOb7RVkTPsZzEanHaH/D6Psr4WJKyd72Wx5wj+bqGh4nPHTFSnK3+gNT4eJAgLvsxLwHxW8QkYYHEdZe8Wd6sOdal9geeLZ8fG9xELYEtuJR6lww5uLvFv/cw= - - secure: DoBz8LDaS4/lQ9sTXE5pnp8fqEvG47mmdQaQ14EnHQ+wLbajIaLk59vRfau5c7mIef8dEgaT40r/kVP5QRr3OiH5UJY3jLnCMVIxWJ3ZTkuGGuU6QDQvoGSSBhdA+b+G94bbK6LtHQxRBrkiyT9d0IzT5ZiHlDlteGbjdDWAgw0=
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/.bower.json index c8a556e..3911d545 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/.bower.json
@@ -1,12 +1,10 @@ { "name": "iron-overlay-behavior", - "version": "1.0.9", + "version": "1.1.1", "license": "http://polymer.github.io/LICENSE.txt", "description": "Provides a behavior for making an element an overlay", "private": true, - "main": [ - "iron-overlay-behavior.html" - ], + "main": "iron-overlay-behavior.html", "keywords": [ "web-components", "polymer", @@ -31,15 +29,16 @@ "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/iron-overlay-behavior", - "_release": "1.0.9", + "_release": "1.1.1", "_resolution": { "type": "version", - "tag": "v1.0.9", - "commit": "87f7763d323fffa07357a08777ad831b7c2c2fb8" + "tag": "v1.1.1", + "commit": "1ed1603ce820456feab3f62ae86f8f3ec801d131" }, "_source": "git://github.com/PolymerElements/iron-overlay-behavior.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/README.md b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/README.md index 27f65d89..bc5c60e 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/README.md
@@ -1,11 +1,69 @@ -# iron-overlay-behavior -Makes an element an overlay with an optional backdrop. -`iron-overlay-behavior` displays an element on top of other content. It starts out hidden and is -displayed by calling `open()` or setting the `opened` property to `true`. It may be closed by -calling `close()` or `cancel()`, or by setting the `opened` property to `false`. +<!--- -The difference between `close()` and `cancel()` is user intent. `close()` generally implies that -the user acknowledged the content of the overlay. By default, it will cancel whenever the user taps -outside it or presses the escape key. This behavior can be turned off via the `no-cancel-on-esc-key` -and the `no-cancel-on-outside-click` properties. +This README is automatically generated from the comments in these files: +iron-overlay-backdrop.html iron-overlay-behavior.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-overlay-behavior) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-overlay-behavior)_ + + +##<iron-overlay-backdrop> + + +`iron-overlay-backdrop` is a backdrop used by `Polymer.IronOverlayBehavior`. It should be a +singleton. + +### Styling + +The following custom properties and mixins are available for styling. + +Custom property | Description | Default +-------------------------------------------|------------------------|--------- +`--iron-overlay-backdrop-background-color` | Backdrop background color | #000 +`--iron-overlay-backdrop-opacity` | Backdrop opacity | 0.6 +`--iron-overlay-backdrop` | Mixin applied to `iron-overlay-backdrop`. | {} +`--iron-overlay-backdrop-opened` | Mixin applied to `iron-overlay-backdrop` when it is displayed | {} + + +##Polymer.IronOverlayBehavior + + +Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden or shown, and displays +on top of other content. It includes an optional backdrop, and can be used to implement a variety +of UI controls including dialogs and drop downs. Multiple overlays may be displayed at once. + +### Closing and canceling + +A dialog may be hidden by closing or canceling. The difference between close and cancel is user +intent. Closing generally implies that the user acknowledged the content on the overlay. By default, +it will cancel whenever the user taps outside it or presses the escape key. This behavior is +configurable with the `no-cancel-on-esc-key` and the `no-cancel-on-outside-click` properties. +`close()` should be called explicitly by the implementer when the user interacts with a control +in the overlay element. When the dialog is canceled, the overlay fires an 'iron-overlay-canceled' +event. Call `preventDefault` on this event to prevent the overlay from closing. + +### Positioning + +By default the element is sized and positioned to fit and centered inside the window. You can +position and size it manually using CSS. See `Polymer.IronFitBehavior`. + +### Backdrop + +Set the `with-backdrop` attribute to display a backdrop behind the overlay. The backdrop is +appended to `<body>` and is of type `<iron-overlay-backdrop>`. See its doc page for styling +options. + +### Limitations + +The element is styled to appear on top of other content by setting its `z-index` property. You +must ensure no element has a stacking context with a higher `z-index` than its parent stacking +context. You should place this element as a child of `<body>` whenever possible. + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/bower.json index 30a3f04..0066027 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/bower.json
@@ -1,12 +1,10 @@ { "name": "iron-overlay-behavior", - "version": "1.0.9", + "version": "1.1.1", "license": "http://polymer.github.io/LICENSE.txt", "description": "Provides a behavior for making an element an overlay", "private": true, - "main": [ - "iron-overlay-behavior.html" - ], + "main": "iron-overlay-behavior.html", "keywords": [ "web-components", "polymer", @@ -31,7 +29,8 @@ "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior-extracted.js index 76907c3..5ce3274 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior-extracted.js
@@ -416,6 +416,12 @@ */ /** + * Fired when the `iron-overlay` is canceled, but before it is closed. + * Cancel the event to prevent the `iron-overlay` from closing. + * @event iron-overlay-canceled + */ + +/** * Fired after the `iron-overlay` closes. * @event iron-overlay-closed * @param {{canceled: (boolean|undefined)}} set to the `closingReason` attribute
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js index 128a382..222dddd 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/iron-overlay-manager-extracted.js
@@ -1,57 +1,71 @@ -Polymer.IronOverlayManager = (function() { +Polymer.IronOverlayManager = { - var overlays = []; - var DEFAULT_Z = 10; - var backdrops = []; + _overlays: [], + + // iframes have a default z-index of 100, so this default should be at least + // that. + _minimumZ: 101, + + _backdrops: [], + + _applyOverlayZ: function(overlay, aboveZ) { + this._setZ(overlay, aboveZ + 2); + }, + + _setZ: function(element, z) { + element.style.zIndex = z; + }, // track overlays for z-index and focus managemant - function addOverlay(overlay) { - var z0 = currentOverlayZ(); - overlays.push(overlay); - var z1 = currentOverlayZ(); - if (z1 <= z0) { - applyOverlayZ(overlay, z0); + addOverlay: function(overlay) { + var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ); + this._overlays.push(overlay); + var newZ = this.currentOverlayZ(); + if (newZ <= minimumZ) { + this._applyOverlayZ(overlay, minimumZ); } - } + }, - function removeOverlay(overlay) { - var i = overlays.indexOf(overlay); + removeOverlay: function(overlay) { + var i = this._overlays.indexOf(overlay); if (i >= 0) { - overlays.splice(i, 1); - setZ(overlay, ''); + this._overlays.splice(i, 1); + this._setZ(overlay, ''); } - } + }, - function applyOverlayZ(overlay, aboveZ) { - setZ(overlay, aboveZ + 2); - } - - function setZ(element, z) { - element.style.zIndex = z; - } - - function currentOverlay() { - var i = overlays.length - 1; - while (overlays[i] && !overlays[i].opened) { + currentOverlay: function() { + var i = this._overlays.length - 1; + while (this._overlays[i] && !this._overlays[i].opened) { --i; } - return overlays[i]; - } + return this._overlays[i]; + }, - function currentOverlayZ() { - var z; - var current = currentOverlay(); + currentOverlayZ: function() { + var z = this._minimumZ; + var current = this.currentOverlay(); if (current) { var z1 = window.getComputedStyle(current).zIndex; if (!isNaN(z1)) { z = Number(z1); } } - return z || DEFAULT_Z; - } + return z; + }, - function focusOverlay() { - var current = currentOverlay(); + /** + * Ensures that the minimum z-index of new overlays is at least `minimumZ`. + * This does not effect the z-index of any existing overlays. + * + * @param {number} minimumZ + */ + ensureMinimumZ: function(minimumZ) { + this._minimumZ = Math.max(this._minimumZ, minimumZ); + }, + + focusOverlay: function() { + var current = this.currentOverlay(); // We have to be careful to focus the next overlay _after_ any current // transitions are complete (due to the state being toggled prior to the // transition). Otherwise, we risk infinite recursion when a transitioning @@ -63,33 +77,23 @@ if (current && !current.transitioning) { current._applyFocus(); } - } + }, - function trackBackdrop(element) { + trackBackdrop: function(element) { // backdrops contains the overlays with a backdrop that are currently // visible if (element.opened) { - backdrops.push(element); + this._backdrops.push(element); } else { - var index = backdrops.indexOf(element); + var index = this._backdrops.indexOf(element); if (index >= 0) { - backdrops.splice(index, 1); + this._backdrops.splice(index, 1); } } + }, + + getBackdrops: function() { + return this._backdrops; } - function getBackdrops() { - return backdrops; - } - - return { - addOverlay: addOverlay, - removeOverlay: removeOverlay, - currentOverlay: currentOverlay, - currentOverlayZ: currentOverlayZ, - focusOverlay: focusOverlay, - trackBackdrop: trackBackdrop, - getBackdrops: getBackdrops - }; - - })(); \ No newline at end of file + }; \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/iron-pages/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-pages/.bower.json index da5d7722..ac5eaea6 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-pages/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-pages/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-pages", - "version": "1.0.3", + "version": "1.0.4", "license": "http://polymer.github.io/LICENSE.txt", "description": "Organizes a set of pages and shows one at a time", "main": "iron-pages.html", @@ -26,15 +26,16 @@ "paper-styles": "polymerelements/paper-styles#^1.0.2", "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/iron-pages", - "_release": "1.0.3", + "_release": "1.0.4", "_resolution": { "type": "version", - "tag": "v1.0.3", - "commit": "ca6e7892786d60d8cb6935d8376b27c3851fdbf5" + "tag": "v1.0.4", + "commit": "238695c7ebf765af321e81c9a5a33a7733f1f6bf" }, "_source": "git://github.com/PolymerElements/iron-pages.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-pages/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-pages/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-pages/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-pages/README.md b/third_party/polymer/v1_0/components-chromium/iron-pages/README.md index 716ccc3..0ff9a5b 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-pages/README.md +++ b/third_party/polymer/v1_0/components-chromium/iron-pages/README.md
@@ -1,22 +1,38 @@ -iron-pages -========== + +<!--- + +This README is automatically generated from the comments in these files: +iron-pages.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/iron-pages) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/iron-pages)_ + + +##<iron-pages> + `iron-pages` is used to select one of its children to show. One use is to cycle through a list of children "pages". Example: -```html -<iron-pages selected="0"> - <div>One</div> - <div>Two</div> - <div>Three</div> -</iron-pages> + <iron-pages selected="0"> + <div>One</div> + <div>Two</div> + <div>Three</div> + </iron-pages> -<script> - document.addEventListener('click', function(e) { - var pages = document.querySelector('iron-pages'); - pages.selectNext(); - }); -</script> -``` + <script> + document.addEventListener('click', function(e) { + var pages = document.querySelector('iron-pages'); + pages.selectNext(); + }); + </script> + +
diff --git a/third_party/polymer/v1_0/components-chromium/iron-pages/bower.json b/third_party/polymer/v1_0/components-chromium/iron-pages/bower.json index e8930e2..90afdd1 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-pages/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-pages/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-pages", - "version": "1.0.3", + "version": "1.0.4", "license": "http://polymer.github.io/LICENSE.txt", "description": "Organizes a set of pages and shows one at a time", "main": "iron-pages.html", @@ -26,7 +26,8 @@ "paper-styles": "polymerelements/paper-styles#^1.0.2", "iron-component-page": "polymerelements/iron-component-page#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-selector/.travis.yml b/third_party/polymer/v1_0/components-chromium/iron-selector/.travis.yml deleted file mode 100644 index eca93211..0000000 --- a/third_party/polymer/v1_0/components-chromium/iron-selector/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: ltCkwJM0nkTS9WjikyjqBsB5J2hQon4UnVVrINk4y+Vq4v9PQJH3+83nya0jnxilKaeAJs4d2/OS02F9GkqYpsSmDz7OgXPfk0hrHA8UksvvpSALfnukleIAN2YTOcxXJKeNHcfpqCKPk1dGeNQOEM61H+QgTBIyFB3sMugygqs= - - secure: TJuu1WdpFLTaBN/prBafm8Pld/BQCySNuuG1nATbF3fqiOpgehXu8Z5URAz5syUhqZAyEmuRMxvXpEVD/t1jrtaXVwkdCFkkQ4ckkP4gTIeSGA/Puw8sveB2q7QAqXyTmeFkocNlh8fxV+B07o0SPWdhcvdZnDVU9VrpSqL+92M=
diff --git a/third_party/polymer/v1_0/components-chromium/iron-test-helpers/.bower.json b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/.bower.json index 46c9cf5..7ed222c 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-test-helpers/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/.bower.json
@@ -1,6 +1,6 @@ { "name": "iron-test-helpers", - "version": "1.0.6", + "version": "1.1.0", "authors": [ "The Polymer Authors" ], @@ -25,11 +25,12 @@ "devDependencies": { "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.6", + "main": "iron-test-helpers.html", + "_release": "1.1.0", "_resolution": { "type": "version", - "tag": "v1.0.6", - "commit": "940e5b8c5c7c878f51cf259019d3e3243f18d0b3" + "tag": "v1.1.0", + "commit": "edc7a68a13447ac2d4b609ac78e57dd7ca5a5a2a" }, "_source": "git://github.com/PolymerElements/iron-test-helpers.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-test-helpers/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/iron-test-helpers/bower.json b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/bower.json index 53e335fd..866fa738 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-test-helpers/bower.json +++ b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/bower.json
@@ -1,6 +1,6 @@ { "name": "iron-test-helpers", - "version": "1.0.6", + "version": "1.1.0", "authors": [ "The Polymer Authors" ], @@ -24,5 +24,6 @@ }, "devDependencies": { "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "main": "iron-test-helpers.html" }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js index 52b52b1..10e46a4 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js +++ b/third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js
@@ -107,14 +107,16 @@ } function focus(target) { - Polymer.Base.fire.call(target, 'focus', {}, { - bubbles: false + Polymer.Base.fire('focus', {}, { + bubbles: false, + node: target }); } function blur(target) { - Polymer.Base.fire.call(target, 'blur', {}, { - bubbles: false + Polymer.Base.fire('blur', {}, { + bubbles: false, + node: target }); }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-behaviors/.bower.json index 3579b52..713d584 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-behaviors", - "version": "1.0.9", + "version": "1.0.10", "description": "Common behaviors across the paper elements", "authors": [ "The Polymer Authors" @@ -27,7 +27,7 @@ "dependencies": { "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0", "iron-checked-element-behavior": "PolymerElements/iron-checked-element-behavior#^1.0.0", - "polymer": "Polymer/polymer#^1.0.0" + "polymer": "Polymer/polymer#^1.2.1" }, "devDependencies": { "iron-component-page": "polymerelements/iron-component-page#^1.0.0", @@ -35,14 +35,15 @@ "paper-material": "PolymerElements/paper-material#^1.0.0", "paper-ripple": "PolymerElements/paper-ripple#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.9", + "ignore": [], + "_release": "1.0.10", "_resolution": { "type": "version", - "tag": "v1.0.9", - "commit": "d9c0398cbaf3881bef3533b5b2b6127fc4d0960c" + "tag": "v1.0.10", + "commit": "4b244a542af2c6c271498dfb98b00ed284df1d6a" }, "_source": "git://github.com/PolymerElements/paper-behaviors.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-behaviors/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/README.md b/third_party/polymer/v1_0/components-chromium/paper-behaviors/README.md index e793a621..43c1b67 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/README.md
@@ -1,4 +1,43 @@ -paper-behaviors -=============== -These are common behaviors used across `paper-*` elements. +<!--- + +This README is automatically generated from the comments in these files: +paper-button-behavior.html paper-checked-element-behavior.html paper-inky-focus-behavior.html paper-ripple-behavior.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-behaviors) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-behaviors)_ + + +<!-- No docs for Polymer.PaperButtonBehavior found. --> + +##Polymer.PaperRippleBehavior + + +`Polymer.PaperRippleBehavior` dynamically implements a ripple +when the element has focus via pointer or keyboard. + +NOTE: This behavior is intended to be used in conjunction with and after +`Polymer.IronButtonState` and `Polymer.IronControlState`. + + + +##Polymer.PaperCheckedElementBehavior + + +Use `Polymer.PaperCheckedElementBehavior` to implement a custom element +that has a `checked` property similar to `Polymer.IronCheckedElementBehavior` +and is compatible with having a ripple effect. + + +##Polymer.PaperInkyFocusBehavior + + +`Polymer.PaperInkyFocusBehavior` implements a ripple when the element has keyboard focus. + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json b/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json index 8446398..a3e0e8b 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-behaviors", - "version": "1.0.9", + "version": "1.0.10", "description": "Common behaviors across the paper elements", "authors": [ "The Polymer Authors" @@ -27,7 +27,7 @@ "dependencies": { "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0", "iron-checked-element-behavior": "PolymerElements/iron-checked-element-behavior#^1.0.0", - "polymer": "Polymer/polymer#^1.0.0" + "polymer": "Polymer/polymer#^1.2.1" }, "devDependencies": { "iron-component-page": "polymerelements/iron-component-page#^1.0.0", @@ -35,7 +35,8 @@ "paper-material": "PolymerElements/paper-material#^1.0.0", "paper-ripple": "PolymerElements/paper-ripple#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/index.html b/third_party/polymer/v1_0/components-chromium/paper-behaviors/index.html index 3e003cb..37184eaa 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/index.html +++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/index.html
@@ -2,11 +2,11 @@ <!-- @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 +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 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <html> <head>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js index ae3493da..ca6f6e0 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js
@@ -51,10 +51,10 @@ /** * Ensures this element contains a ripple effect. For startup efficiency * the ripple effect is dynamically on demand when needed. - * @param {!Event=} opt_triggeringEvent (optional) event that triggered the + * @param {!Event=} optTriggeringEvent (optional) event that triggered the * ripple. */ - ensureRipple: function(opt_triggeringEvent) { + ensureRipple: function(optTriggeringEvent) { if (!this.hasRipple()) { this._ripple = this._createRipple(); this._ripple.noink = this.noink; @@ -62,12 +62,14 @@ if (rippleContainer) { Polymer.dom(rippleContainer).appendChild(this._ripple); } - var domContainer = rippleContainer === this.shadyRoot ? this : - rippleContainer; - if (opt_triggeringEvent) { - var target = opt_triggeringEvent.target; - if (domContainer.contains(/** @type {Node} */(target))) { - this._ripple.uiDownAction(opt_triggeringEvent); + if (optTriggeringEvent) { + // Check if the event happened inside of the ripple container + // Fall back to host instead of the root because distributed text + // nodes are not valid event targets + var domContainer = Polymer.dom(this._rippleContainer || this); + var target = Polymer.dom(optTriggeringEvent).rootTarget; + if (domContainer.deepContains( /** @type {Node} */(target))) { + this._ripple.uiDownAction(optTriggeringEvent); } } }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-card/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-card/.bower.json index f037d0a..5ad26518 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-card/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-card/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-card", - "version": "1.0.7", + "version": "1.0.8", "description": "Material design piece of paper with unique related data", "authors": [ "The Polymer Authors" @@ -10,9 +10,7 @@ "polymer", "card" ], - "main": [ - "paper-card.html" - ], + "main": "paper-card.html", "private": true, "repository": { "type": "git", @@ -22,25 +20,27 @@ "homepage": "https://github.com/PolymerElements/paper-card", "ignore": [], "dependencies": { - "polymer": "Polymer/polymer#^1.1.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "iron-image": "PolymerElements/iron-image#~1.0.2", "paper-material": "PolymerElements/paper-material#^1.0.0", - "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0" + "polymer": "Polymer/polymer#^1.1.0" }, "devDependencies": { + "iron-collapse": "PolymerElements/iron-collapse#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "paper-button": "PolymerElements/paper-button#^1.0.0", + "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", + "paper-styles": "PolymerElements/paper-styles#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "web-component-tester": "*", - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", - "paper-button": "PolymerElements/paper-button#^1.0.0", - "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", - "paper-styles": "PolymerElements/paper-styles#^1.0.0" + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.7", + "_release": "1.0.8", "_resolution": { "type": "version", - "tag": "v1.0.7", - "commit": "a1a0b2789b657a9b2bce17483ecc495ce968b104" + "tag": "v1.0.8", + "commit": "3144145f93eba7208b55c4c9be5cf3d861c2a736" }, "_source": "git://github.com/PolymerElements/paper-card.git", "_target": "*",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-card/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-card/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-card/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-card/README.md b/third_party/polymer/v1_0/components-chromium/paper-card/README.md index db0d78b..58c50c8a 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-card/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-card/README.md
@@ -1,20 +1,43 @@ -# paper-card -Material Design: <a href="http://www.google.com/design/spec/components/cards.html">Cards</a> +<!--- + +This README is automatically generated from the comments in these files: +paper-card.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-card) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-card)_ + + +##<paper-card> + + +Material design: [Cards](https://www.google.com/design/spec/components/cards.html) `paper-card` is a container with a drop shadow. Example: -```html -<paper-card heading="Card Title"> - <div class="card-content">Some content</div> - <div class="card-actions"> - <paper-button>Some action</paper-button> - </div> -</paper-card> -``` + + <paper-card heading="Card Title"> + <div class="card-content">Some content</div> + <div class="card-actions"> + <paper-button>Some action</paper-button> + </div> + </paper-card> + +Example - top card image: + + <paper-card heading="Card Title" image="/path/to/image.png"> + ... + </paper-card> ### Accessibility + By default, the `aria-label` will be set to the value of the `heading` attribute. ### Styling @@ -25,6 +48,11 @@ ----------------|-------------|---------- `--paper-card-header-color` | The color of the header text | `#000` `--paper-card-header` | Mixin applied to the card header section | `{}` +`--paper-card-header-text` | Mixin applied to the title in the card header section | `{}` +`--paper-card-header-image` | Mixin applied to the image in the card header section | `{}` +`--paper-card-header-image-text` | Mixin applied to the text overlapping the image in the card header section | `{}` `--paper-card-content` | Mixin applied to the card content section| `{}` `--paper-card-actions` | Mixin applied to the card action section | `{}` `--paper-card` | Mixin applied to the card | `{}` + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-card/bower.json b/third_party/polymer/v1_0/components-chromium/paper-card/bower.json index 7e4b7ccc7..28ebc23e 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-card/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-card/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-card", - "version": "1.0.7", + "version": "1.0.8", "description": "Material design piece of paper with unique related data", "authors": [ "The Polymer Authors" @@ -10,9 +10,7 @@ "polymer", "card" ], - "main": [ - "paper-card.html" - ], + "main": "paper-card.html", "private": true, "repository": { "type": "git", @@ -22,18 +20,20 @@ "homepage": "https://github.com/PolymerElements/paper-card", "ignore": [], "dependencies": { - "polymer": "Polymer/polymer#^1.1.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "iron-image": "PolymerElements/iron-image#~1.0.2", "paper-material": "PolymerElements/paper-material#^1.0.0", - "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0" + "polymer": "Polymer/polymer#^1.1.0" }, "devDependencies": { + "iron-collapse": "PolymerElements/iron-collapse#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "paper-button": "PolymerElements/paper-button#^1.0.0", + "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", + "paper-styles": "PolymerElements/paper-styles#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "web-component-tester": "*", - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", - "paper-button": "PolymerElements/paper-button#^1.0.0", - "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", - "paper-styles": "PolymerElements/paper-styles#^1.0.0" + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-card/paper-card-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-card/paper-card-extracted.js index 7b684d6..8dddd7c 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-card/paper-card-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-card/paper-card-extracted.js
@@ -22,6 +22,24 @@ }, /** + * When `true`, any change to the image url property will cause the + * `placeholder` image to be shown until the image is fully rendered. + */ + preloadImage: { + type: Boolean, + value: false + }, + + /** + * When `preloadImage` is true, setting `fadeImage` to true will cause the + * image to fade into place. + */ + fadeImage: { + type: Boolean, + value: false + }, + + /** * The z-depth of the card, from 0-5. */ elevation: {
diff --git a/third_party/polymer/v1_0/components-chromium/paper-card/paper-card.html b/third_party/polymer/v1_0/components-chromium/paper-card/paper-card.html index b1c09ac..71fbb38 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-card/paper-card.html +++ b/third_party/polymer/v1_0/components-chromium/paper-card/paper-card.html
@@ -9,6 +9,7 @@ --><html><head><link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../paper-material/paper-material.html"> <link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../iron-image/iron-image.html"> <!-- Material design: [Cards](https://www.google.com/design/spec/components/cards.html) @@ -80,8 +81,9 @@ @apply(--paper-card-header); } - .header img { + .header iron-image { width: 100%; + --iron-image-width: 100%; pointer-events: none; @apply(--paper-card-header-image); } @@ -89,7 +91,7 @@ .header .title-text { padding: 16px; font-size: 24px; - font-weight: bold; + font-weight: 400; color: var(--paper-card-header-color, #000); @apply(--paper-card-header-text); } @@ -115,7 +117,7 @@ </style> <div class="header"> - <img hidden$="[[!image]]" src="[[image]]"> + <iron-image hidden$="[[!image]]" src="[[image]]" preload$="[[preloadImage]]" fade$="[[fadeImage]]"></iron-image> <div hidden$="[[!heading]]" class$="[[_computeHeadingClass(image)]]">[[heading]]</div> </div>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-checkbox/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-checkbox/.bower.json index b253cdd..37910733 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-checkbox/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-checkbox/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-checkbox", - "version": "1.0.14", + "version": "1.0.15", "description": "A material design checkbox", "authors": [ "The Polymer Authors" @@ -36,11 +36,11 @@ "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0" }, "main": "paper-checkbox.html", - "_release": "1.0.14", + "_release": "1.0.15", "_resolution": { "type": "version", - "tag": "v1.0.14", - "commit": "be311b93234bbb15b527220ace17a30706657948" + "tag": "v1.0.15", + "commit": "fe884a3da56b03998731d5ae299dd2fe893b3b8a" }, "_source": "git://github.com/PolymerElements/paper-checkbox.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-checkbox/.travis.yml b/third_party/polymer/v1_0/components-chromium/paper-checkbox/.travis.yml deleted file mode 100644 index 2eabb9e..0000000 --- a/third_party/polymer/v1_0/components-chromium/paper-checkbox/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: PkxMaBcKe8HD1Jv8O6qiyQ4Nux6DfaVyN/ss9opajX9Oqa2ECJRI/OCsjDSrgXKhuAc2dw0L/KwSb/j4hg3/9BzHlJYQmeR9b9+MsO377TseNw5aKlywgVRu2bj8ODv2naQ4pB4B/Us/n9K7J0vlHIwM8UAJJwGjYm2oYTQxCAw= - - secure: WQNRMEQEm6k5e+rzN08Lg0IBC83AZLz1QLP89z59JHLrAOeBu7CBh/LFG0OkhUnTC+dG2JdfIZbdQVCEciDyONjSIKzmM4ze9/LrGzFpROE8bU0ylYSLqX+3CK/6i7VMR3pJo79e1KOeprppHiJSRLVBJfhG+5uNgwAXws/sLQ4=
diff --git a/third_party/polymer/v1_0/components-chromium/paper-checkbox/README.md b/third_party/polymer/v1_0/components-chromium/paper-checkbox/README.md index a3abdfa..6434b43 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-checkbox/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-checkbox/README.md
@@ -2,7 +2,7 @@ <!--- This README is automatically generated from the comments in these files: -metadata.html paper-checkbox.html +paper-checkbox.html Edit those files, and our readme bot will duplicate them over here! Edit this file, and the bot will squash your changes :)
diff --git a/third_party/polymer/v1_0/components-chromium/paper-checkbox/bower.json b/third_party/polymer/v1_0/components-chromium/paper-checkbox/bower.json index 5e3598d..f8ce1f2 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-checkbox/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-checkbox/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-checkbox", - "version": "1.0.14", + "version": "1.0.15", "description": "A material design checkbox", "authors": [ "The Polymer Authors"
diff --git a/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html b/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html index ffaf078..7cd8436 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html +++ b/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html
@@ -68,6 +68,7 @@ position: relative; width: 18px; height: 18px; + min-width: 18px; vertical-align: middle; background-color: var(--paper-checkbox-unchecked-background-color, transparent); } @@ -112,31 +113,19 @@ @-webkit-keyframes checkmark-expand { 0% { - top: 9px; - left: 6px; - width: 0px; - height: 0px; + -webkit-transform: scale(0, 0) rotate(45deg); } 100% { - top: -1px; - left: 4px; - width: 5px; - height: 10px; + -webkit-transform: scale(1, 1) rotate(45deg); } } @keyframes checkmark-expand { 0% { - top: 9px; - left: 6px; - width: 0px; - height: 0px; + transform: scale(0, 0) rotate(45deg); } 100% { - top: -1px; - left: 4px; - width: 5px; - height: 10px; + transform: scale(1, 1) rotate(45deg); } } @@ -146,11 +135,7 @@ } #checkmark { - -webkit-transform: rotate(45deg); - transform: rotate(45deg); position: absolute; - top: -1px; - left: 4px; width: 5px; height: 10px; border-style: solid; @@ -159,6 +144,8 @@ border-right-width: 2px; border-bottom-width: 2px; border-color: var(--paper-checkbox-checkmark-color, white); + transform-origin: 97% 86%; + -webkit-transform-origin: 97% 86%; } /* label */
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/.bower.json index 8fcd1259..fc4c6b9 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-dialog-behavior", - "version": "1.0.6", + "version": "1.1.0", "description": "Implements a behavior used for material design dialogs", "authors": "The Polymer Authors", "keywords": [ @@ -10,9 +10,7 @@ "overlay", "behavior" ], - "main": [ - "paper-dialog-behavior.html" - ], + "main": "paper-dialog-behavior.html", "private": true, "repository": { "type": "git", @@ -24,7 +22,7 @@ "dependencies": { "iron-overlay-behavior": "PolymerElements/iron-overlay-behavior#^1.0.0", "paper-styles": "PolymerElements/paper-styles#^1.0.4", - "polymer": "Polymer/polymer#^1.0.0" + "polymer": "Polymer/polymer#^1.1.0" }, "devDependencies": { "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", @@ -34,11 +32,11 @@ "web-component-tester": "*", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.6", + "_release": "1.1.0", "_resolution": { "type": "version", - "tag": "v1.0.6", - "commit": "9714b11aa532e1a59dadc2096616ed2ea3b82157" + "tag": "v1.1.0", + "commit": "e41d36a798df2ee2f9f49fb27dd7712e55366595" }, "_source": "git://github.com/PolymerElements/paper-dialog-behavior.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/README.md b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/README.md index 2c63d3c..af0983d 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/README.md
@@ -1,24 +1,64 @@ -# paper-dialog-behavior -`paper-dialog-behavior` implements behavior related to a Material Design dialog. Use this behavior -and include `paper-dialog-common.css` in your element to implement a dialog. +<!--- + +This README is automatically generated from the comments in these files: +paper-dialog-behavior.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-dialog-behavior) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-dialog-behavior)_ + + +##Polymer.PaperDialogBehavior + + +Use `Polymer.PaperDialogBehavior` and `paper-dialog-common.css` to implement a Material Design +dialog. + +For example, if `<paper-dialog-impl>` implements this behavior: + + <paper-dialog-impl> + <h2>Header</h2> + <div>Dialog body</div> + <div class="buttons"> + <paper-button dialog-dismiss>Cancel</paper-button> + <paper-button dialog-confirm>Accept</paper-button> + </div> + </paper-dialog-impl> `paper-dialog-common.css` provide styles for a header, content area, and an action area for buttons. Use the `<h2>` tag for the header and the `buttons` class for the action area. You can use the `paper-dialog-scrollable` element (in its own repository) if you need a scrolling content area. Use the `dialog-dismiss` and `dialog-confirm` attributes on interactive controls to close the -dialog. +dialog. If the user dismisses the dialog with `dialog-confirm`, the `closingReason` will update +to include `confirmed: true`. -For example, if `<paper-dialog-impl>` implements this behavior: +### Styling -```html -<paper-dialog-impl> - <h2>Header</h2> - <div>Dialog body</div> - <div class="buttons"> - <paper-button dialog-dismiss>Cancel</paper-button> - <paper-button dialog-confirm>Accept</paper-button> - </div> -</paper-dialog-impl> -``` +The following custom properties and mixins are available for styling. + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-dialog-background-color` | Dialog background color | `--primary-background-color` +`--paper-dialog-color` | Dialog foreground color | `--primary-text-color` +`--paper-dialog` | Mixin applied to the dialog | `{}` +`--paper-dialog-title` | Mixin applied to the title (`<h2>`) element | `{}` +`--paper-dialog-button-color` | Button area foreground color | `--default-primary-color` + +### Accessibility + +This element has `role="dialog"` by default. Depending on the context, it may be more appropriate +to override this attribute with `role="alertdialog"`. + +If `modal` is set, the element will set `aria-modal` and prevent the focus from exiting the element. +It will also ensure that focus remains in the dialog. + +The `aria-labelledby` attribute will be set to the header element, if one exists. + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/bower.json index f3585fa..ef81a9e 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-dialog-behavior", - "version": "1.0.6", + "version": "1.1.0", "description": "Implements a behavior used for material design dialogs", "authors": "The Polymer Authors", "keywords": [ @@ -10,9 +10,7 @@ "overlay", "behavior" ], - "main": [ - "paper-dialog-behavior.html" - ], + "main": "paper-dialog-behavior.html", "private": true, "repository": { "type": "git", @@ -24,7 +22,7 @@ "dependencies": { "iron-overlay-behavior": "PolymerElements/iron-overlay-behavior#^1.0.0", "paper-styles": "PolymerElements/paper-styles#^1.0.4", - "polymer": "Polymer/polymer#^1.0.0" + "polymer": "Polymer/polymer#^1.1.0" }, "devDependencies": { "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior-extracted.js index 38a1200..6d528e2 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior-extracted.js
@@ -1,5 +1,5 @@ /** -Use `Polymer.PaperDialogBehavior` and `paper-dialog-common.css` to implement a Material Design +Use `Polymer.PaperDialogBehavior` and `paper-dialog-shared-styles.html` to implement a Material Design dialog. For example, if `<paper-dialog-impl>` implements this behavior: @@ -13,7 +13,7 @@ </div> </paper-dialog-impl> -`paper-dialog-common.css` provide styles for a header, content area, and an action area for buttons. +`paper-dialog-shared-styles.html` provide styles for a header, content area, and an action area for buttons. Use the `<h2>` tag for the header and the `buttons` class for the action area. You can use the `paper-dialog-scrollable` element (in its own repository) if you need a scrolling content area.
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior.html b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior.html index 9d24b77..03ec6d46 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior.html +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-behavior.html
@@ -8,6 +8,9 @@ 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-overlay-behavior/iron-overlay-behavior.html"> -<link rel="import" href="../paper-styles/paper-styles.html"> +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../paper-styles/default-theme.html"> +<link rel="import" href="../paper-styles/typography.html"> +<link rel="import" href="../paper-styles/shadow.html"> </head><body><script src="paper-dialog-behavior-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-shared-styles.html b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-shared-styles.html new file mode 100644 index 0000000..face2497 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-shared-styles.html
@@ -0,0 +1,64 @@ +<!-- +@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 +--> + +<dom-module id="paper-dialog-shared-styles"> + <template> + <style> + :host { + display: block; + margin: 24px 40px; + -webkit-overflow-scrolling: touch; + + background: var(--paper-dialog-background-color, --primary-background-color); + color: var(--paper-dialog-color, --primary-text-color); + + @apply(--paper-font-body1); + @apply(--shadow-elevation-16dp); + @apply(--paper-dialog); + } + + :host > ::content > * { + margin-top: 20px; + padding: 0 24px; + } + + :host > ::content > .no-padding { + padding: 0; + } + + :host > ::content > *:first-child { + margin-top: 24px; + } + + :host > ::content > *:last-child { + margin-bottom: 24px; + } + + :host > ::content h2 { + position: relative; + margin: 0; + @apply(--paper-font-title); + + @apply(--paper-dialog-title); + } + + :host > ::content .buttons { + position: relative; + padding: 8px 8px 8px 24px; + margin: 0; + + color: var(--paper-dialog-button-color, --default-primary-color); + + @apply(--layout-horizontal); + @apply(--layout-end-justified); + } + </style> + </template> +</dom-module>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-dialog/.bower.json index ac4d829a..90f438f 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog/.bower.json
@@ -1,7 +1,7 @@ { "name": "paper-dialog", "description": "A Material Design dialog", - "version": "1.0.2", + "version": "1.0.3", "authors": "The Polymer Authors", "keywords": [ "web-components", @@ -19,7 +19,7 @@ "homepage": "https://github.com/PolymerElements/paper-dialog", "ignore": [], "dependencies": { - "polymer": "Polymer/polymer#^1.0.0", + "polymer": "Polymer/polymer#^1.1.0", "paper-dialog-behavior": "PolymerElements/paper-dialog-behavior#^1.0.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", "neon-animation": "PolymerElements/neon-animation#^1.0.0" @@ -32,14 +32,14 @@ "paper-item": "PolymerElements/paper-item#^1.0.0", "paper-dialog-scrollable": "PolymerElements/paper-dialog-scrollable#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.2", + "_release": "1.0.3", "_resolution": { "type": "version", - "tag": "v1.0.2", - "commit": "f24bdc41e7374793c5bd966aa8cadc012e15cb09" + "tag": "v1.0.3", + "commit": "ec85b110e11e9d390f601e1c88ebf97984b53d82" }, "_source": "git://github.com/PolymerElements/paper-dialog.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-dialog/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog/README.md b/third_party/polymer/v1_0/components-chromium/paper-dialog/README.md index a4d5c7f..4bcd5d4 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog/README.md
@@ -1,3 +1,68 @@ -# paper-dialog -A Material Design dialog +<!--- + +This README is automatically generated from the comments in these files: +paper-dialog.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-dialog) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-dialog)_ + + +##<paper-dialog> + + +Material design: [Dialogs](https://www.google.com/design/spec/components/dialogs.html) + +`<paper-dialog>` is a dialog with Material Design styling and optional animations when it is +opened or closed. It provides styles for a header, content area, and an action area for buttons. +You can use the `<paper-dialog-scrollable>` element (in its own repository) if you need a scrolling +content area. See `Polymer.PaperDialogBehavior` for specifics. + +For example, the following code implements a dialog with a header, scrolling content area and +buttons. + + <paper-dialog> + <h2>Header</h2> + <paper-dialog-scrollable> + Lorem ipsum... + </paper-dialog-scrollable> + <div class="buttons"> + <paper-button dialog-dismiss>Cancel</paper-button> + <paper-button dialog-confirm>Accept</paper-button> + </div> + </paper-dialog> + +### Styling + +See the docs for `Polymer.PaperDialogBehavior` for the custom properties available for styling +this element. + +### Animations + +Set the `entry-animation` and/or `exit-animation` attributes to add an animation when the dialog +is opened or closed. See the documentation in +[PolymerElements/neon-animation](https://github.com/PolymerElements/neon-animation) for more info. + +For example: + + <link rel="import" href="components/neon-animation/animations/scale-up-animation.html"> + <link rel="import" href="components/neon-animation/animations/fade-out-animation.html"> + + <paper-dialog entry-animation="scale-up-animation" + exit-animation="fade-out-animation"> + <h2>Header</h2> + <div>Dialog body</div> + </paper-dialog> + +### Accessibility + +See the docs for `Polymer.PaperDialogBehavior` for accessibility features implemented by this +element. + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog/bower.json b/third_party/polymer/v1_0/components-chromium/paper-dialog/bower.json index 3fb95a72..ae1aa53c 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog/bower.json
@@ -1,7 +1,7 @@ { "name": "paper-dialog", "description": "A Material Design dialog", - "version": "1.0.2", + "version": "1.0.3", "authors": "The Polymer Authors", "keywords": [ "web-components", @@ -19,7 +19,7 @@ "homepage": "https://github.com/PolymerElements/paper-dialog", "ignore": [], "dependencies": { - "polymer": "Polymer/polymer#^1.0.0", + "polymer": "Polymer/polymer#^1.1.0", "paper-dialog-behavior": "PolymerElements/paper-dialog-behavior#^1.0.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", "neon-animation": "PolymerElements/neon-animation#^1.0.0" @@ -32,7 +32,7 @@ "paper-item": "PolymerElements/paper-item#^1.0.0", "paper-dialog-scrollable": "PolymerElements/paper-dialog-scrollable#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dialog/paper-dialog.html b/third_party/polymer/v1_0/components-chromium/paper-dialog/paper-dialog.html index 194ff73..86ed386 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-dialog/paper-dialog.html +++ b/third_party/polymer/v1_0/components-chromium/paper-dialog/paper-dialog.html
@@ -9,12 +9,13 @@ --><html><head><link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../neon-animation/neon-animation-runner-behavior.html"> <link rel="import" href="../paper-dialog-behavior/paper-dialog-behavior.html"> -<link rel="import" href="../paper-styles/paper-styles.html"> - +<link rel="import" href="../paper-dialog-behavior/paper-dialog-shared-styles.html"> <!-- +Material design: [Dialogs](https://www.google.com/design/spec/components/dialogs.html) + `<paper-dialog>` is a dialog with Material Design styling and optional animations when it is opened or closed. It provides styles for a header, content area, and an action area for buttons. -You can use the `<paper-dialog-scrollable` element (in its own repository) if you need a scrolling +You can use the `<paper-dialog-scrollable>` element (in its own repository) if you need a scrolling content area. See `Polymer.PaperDialogBehavior` for specifics. For example, the following code implements a dialog with a header, scrolling content area and @@ -65,13 +66,10 @@ --> </head><body><dom-module id="paper-dialog"> - - <link rel="import" type="css" href="../paper-dialog-behavior/paper-dialog-common.css"> - <template> + <style include="paper-dialog-shared-styles"></style> <content></content> </template> - </dom-module> <script src="paper-dialog-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-dropdown-menu/.travis.yml b/third_party/polymer/v1_0/components-chromium/paper-dropdown-menu/.travis.yml deleted file mode 100644 index c9383b47..0000000 --- a/third_party/polymer/v1_0/components-chromium/paper-dropdown-menu/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: Uv6d6W9yI2Lbj7gYh73LCGHpwvvdE1sdqdElVsTN4LSYW4msyLweDD4/Irbk5Nw5bavxkXraYkN655p5VU1SBucTRFMYYtpTDA7xBT/HvXVP3+OgkrN+joVStHcRJXHJCoVtq+YalZ07Q0dltw/brtSUCHhZkcNMxHd/p0NGD1FBSgXC1oXv+MSLjPsSKujz8WuXbfnGXkW682rZhS8Mp5x4Y31AAuGl64gNypAYTdWZ9bKLjeAx4ZY1poiw4Bs1z+V9tO3EeD6YQb/CVpxOH+67FQ2cX0ybLXumNuJQFIzki+EzFwXxuKrJsD4gu8B4kJKVWuAS9wuWkNgGdjR2HVe3/5+nMe7RiLL/wD6yGvcD2ZjP8S0RrxbOeZ03IzadH1NT0FWGf0J55VQgt4XjN0j9bVTYMfX5Xyg5bQ/E1qPzHbyteMAw6LF4Wmh2PyWzKHfz1uPGiZP/3BOKj8EbGMKPBci2181kbotPDENMT/5lk24e944tr7hKWWatNxCmkeb+lJomAxGwDYt2+I4mrpHFz/r4w9qgNr3DelhHTkBw2lNKzGAL5I177IJvsvGnZaCpGuRDWfq2xLGg2aTa9J1iyvil8gQP4CVxffWbqpPxvOax3V5nfbnAUpyYWvCtVSpOV5ndZA9FlBIn/pOsXqIjdiOTmmeJwFoddpCcZ1Y= - - secure: X0QrO1SQJs/ktfeJRfAzSTTAyLeMLu0NB5uj+hQCLPZ6QPacaOEaKmwx57CY2qsD9X34ijtXZHP8A3RWKXeQHt2H4CrQ/drWWzNjKMmaf42w8fzHNKkqlwsQV7Bh/g5qXnbzrkcsViOfDVkyPLIKumyG2NqZPrhjl8QDMGseiELB5oznBH/z8APY3lJVB1baT3Wxyzz7TdAYCpZGfdGjr/3bAx1qBNHJXeEMFJDYH4q2nKfqVhdNQx2VdB6nyxIoGKoDynPIGty2pVPOKrp6ctdJYFwtljbO1/AOh3uvkiZRB1dAwr8vE6xVBcUnpM8vseRhlipCSO6qcNTolF67DzlakjxNd8CUwnokJ1juxH9x4uUTAaUpaAHOFqL130Ogcqye6KJ4RavD9cs198dZE3Al9savUF8N2Q8Mpc04dc7AuMOglTTQqhIpLSdtFWsIptMUmhBS3hMgWfVAH7DEzR41SFwwXCN4ZvYC1ooCJK1+wL2po4kIHRaEHx+L6r+1+RKXQ+zBAG5VMtFtc0OoFtInTvyNqBcyHGkbxQaGdHN1FpBWo3wL5qcP37DtYbGe0iEtASk1w0MLlujQjHIY4smxVB/XmNRiOEkWHAtGxbBOu4NAHU5Qhxe22/w1fgPnO3YRoiNO4liJEYJNN1TpTYO3VolNq0IvdFKswj/p0vM=
diff --git a/third_party/polymer/v1_0/components-chromium/paper-fab/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-fab/.bower.json index 2731e4d..9e3d4ae2 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-fab/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-fab/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-fab", - "version": "1.0.6", + "version": "1.1.0", "description": "A material design floating action button", "authors": [ "The Polymer Authors" @@ -33,14 +33,14 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.6", + "_release": "1.1.0", "_resolution": { "type": "version", - "tag": "v1.0.6", - "commit": "d9d70a86af8464f880d3022bedc08845c3bf2d1d" + "tag": "v1.1.0", + "commit": "03fd1462029c2dd0b9208b6f6511af8d78eb91bd" }, "_source": "git://github.com/PolymerElements/paper-fab.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-fab/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-fab/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-fab/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-fab/README.md b/third_party/polymer/v1_0/components-chromium/paper-fab/README.md index 4ee55de..f2bb1c83 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-fab/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-fab/README.md
@@ -1,7 +1,23 @@ -paper-fab -========= -Material Design: <a href="http://www.google.com/design/spec/components/buttons.html">Button</a> +<!--- + +This README is automatically generated from the comments in these files: +paper-fab.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-fab) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-fab)_ + + +##<paper-fab> + + +Material design: [Floating Action Button](https://www.google.com/design/spec/components/buttons-floating-action-button.html) `paper-fab` is a floating action button. It contains an image placed in the center and comes in two sizes: regular size and a smaller size by applying the attribute `mini`. When @@ -12,10 +28,26 @@ Example: -```html -<link href="path/to/iron-icons/iron-icons.html" rel="import"> + <link href="path/to/iron-icons/iron-icons.html" rel="import"> -<paper-fab icon="add"></paper-fab> -<paper-fab mini icon="favorite"></paper-fab> -<paper-fab src="star.png"></paper-fab> -``` + <paper-fab icon="add"></paper-fab> + <paper-fab mini icon="favorite"></paper-fab> + <paper-fab src="star.png"></paper-fab> + + +### Styling + +The following custom properties and mixins are available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-fab-background` | The background color of the button | `--accent-color` +`--paper-fab-keyboard-focus-background` | The background color of the button when focused | `--paper-pink-900` +`--paper-fab-disabled-background` | The background color of the button when it's disabled | `--paper-grey-300` +`--paper-fab-disabled-text` | The text color of the button when it's disabled | `--paper-grey-500` +`--paper-fab` | Mixin applied to the button | `{}` +`--paper-fab-mini` | Mixin applied to a mini button | `{}` +`--paper-fab-disabled` | Mixin applied to a disabled button | `{}` +`--paper-fab-iron-icon` | Mixin applied to the iron-icon within the button | `{}` + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-fab/bower.json b/third_party/polymer/v1_0/components-chromium/paper-fab/bower.json index a9240a0..e5ac070 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-fab/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-fab/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-fab", - "version": "1.0.6", + "version": "1.1.0", "description": "A material design floating action button", "authors": [ "The Polymer Authors" @@ -33,7 +33,7 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html b/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html index e622143..1ef11d3 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html +++ b/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html
@@ -7,7 +7,7 @@ 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-flex-layout/classes/iron-flex-layout.html"> +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <link rel="import" href="../iron-icon/iron-icon.html"> <link rel="import" href="../paper-behaviors/paper-button-behavior.html"> <link rel="import" href="../paper-material/paper-material.html">
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-input/.bower.json index 706b40f..d0ff753 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-input/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-input", - "version": "1.0.18", + "version": "1.1.1", "description": "Material design text fields", "authors": [ "The Polymer Authors" @@ -27,7 +27,7 @@ "homepage": "https://github.com/PolymerElements/paper-input", "ignore": [], "dependencies": { - "polymer": "Polymer/polymer#^1.2.0", + "polymer": "Polymer/polymer#^1.1.0", "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^1.0.0", "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0", "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#^1.0.0", @@ -35,20 +35,20 @@ "paper-styles": "PolymerElements/paper-styles#^1.0.0" }, "devDependencies": { - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "Polymer/web-component-tester#^3.3.0", - "test-fixture": "PolymerElements/test-fixture#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-icon": "PolymerElements/iron-icon#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0", - "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0" + "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", + "test-fixture": "PolymerElements/test-fixture#^1.0.0", + "web-component-tester": "Polymer/web-component-tester#^3.3.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.0.18", + "_release": "1.1.1", "_resolution": { "type": "version", - "tag": "v1.0.18", - "commit": "8bb2b1972158d3a28ca3a350003b8ca78c147b53" + "tag": "v1.1.1", + "commit": "1bbce220b027dc030b294163f7da6f3e9052ab13" }, "_source": "git://github.com/PolymerElements/paper-input.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-input/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-input/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/README.md b/third_party/polymer/v1_0/components-chromium/paper-input/README.md index c49ccc04..da0569a 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-input/README.md
@@ -1,5 +1,217 @@ -# paper-input -`<paper-input>` is a Material Design text field. +<!--- -Contains a number of different features for validation, character counting, and more. +This README is automatically generated from the comments in these files: +paper-input-addon-behavior.html paper-input-behavior.html paper-input-char-counter.html paper-input-container.html paper-input-error.html paper-input.html paper-textarea.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-input) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-input)_ + + +##<paper-input> + + +Material design: [Text fields](https://www.google.com/design/spec/components/text-fields.html) + +`<paper-input>` is a single-line text field with Material Design styling. + + <paper-input label="Input label"></paper-input> + +It may include an optional error message or character counter. + + <paper-input error-message="Invalid input!" label="Input label"></paper-input> + <paper-input char-counter label="Input label"></paper-input> + +It can also include custom prefix or suffix elements, which are displayed +before or after the text input itself. In order for an element to be +considered as a prefix, it must have the `prefix` attribute (and similarly +for `suffix`). + + <paper-input label="total"> + <div prefix>$</div> + <paper-icon-button suffix icon="clear"></paper-icon-button> + </paper-input> + +A `paper-input` can use the native `type=search` or `type=file` features. +However, since we can't control the native styling of the input, in these cases +it's recommended to use a placeholder text, or `always-float-label`, +as to not overlap the native UI (search icon, file button, etc.). + + <paper-input label="search!" type="search" + placeholder="search for cats" autosave="test" results="5"> + </paper-input> + +See `Polymer.PaperInputBehavior` for more API docs. + +### Styling + +See `Polymer.PaperInputContainer` for a list of custom properties used to +style this element. + + + +##<paper-input-char-counter> + + +`<paper-input-char-counter>` is a character counter for use with `<paper-input-container>`. It +shows the number of characters entered in the input and the max length if it is specified. + + <paper-input-container> + <input is="iron-input" maxlength="20"> + <paper-input-char-counter></paper-input-char-counter> + </paper-input-container> + +### Styling + +The following mixin is available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-input-char-counter` | Mixin applied to the element | `{}` + + +##<paper-input-container> + + +`<paper-input-container>` is a container for a `<label>`, an `<input is="iron-input">` or +`<iron-autogrow-textarea>` and optional add-on elements such as an error message or character +counter, used to implement Material Design text fields. + +For example: + + <paper-input-container> + <label>Your name</label> + <input is="iron-input"> + </paper-input-container> + +### Listening for input changes + +By default, it listens for changes on the `bind-value` attribute on its children nodes and perform +tasks such as auto-validating and label styling when the `bind-value` changes. You can configure +the attribute it listens to with the `attr-for-value` attribute. + +### Using a custom input element + +You can use a custom input element in a `<paper-input-container>`, for example to implement a +compound input field like a social security number input. The custom input element should have the +`paper-input-input` class, have a `notify:true` value property and optionally implements +`Polymer.IronValidatableBehavior` if it is validatable. + + <paper-input-container attr-for-value="ssn-value"> + <label>Social security number</label> + <ssn-input class="paper-input-input"></ssn-input> + </paper-input-container> + +### Validation + +If the `auto-validate` attribute is set, the input container will validate the input and update +the container styling when the input value changes. + +### Add-ons + +Add-ons are child elements of a `<paper-input-container>` with the `add-on` attribute and +implements the `Polymer.PaperInputAddonBehavior` behavior. They are notified when the input value +or validity changes, and may implement functionality such as error messages or character counters. +They appear at the bottom of the input. + +### Prefixes and suffixes +These are child elements of a `<paper-input-container>` with the `prefix` +or `suffix` attribute, and are displayed inline with the input, before or after. + + <paper-input-container> + <div prefix>$</div> + <label>Total</label> + <input is="iron-input"> + <paper-icon-button suffix icon="clear"></paper-icon-button> + </paper-input-container> + +### Styling + +The following custom properties and mixins are available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-input-container-color` | Label and underline color when the input is not focused | `--secondary-text-color` +`--paper-input-container-focus-color` | Label and underline color when the input is focused | `--default-primary-color` +`--paper-input-container-invalid-color` | Label and underline color when the input is is invalid | `--google-red-500` +`--paper-input-container-input-color` | Input foreground color | `--primary-text-color` +`--paper-input-container` | Mixin applied to the container | `{}` +`--paper-input-container-disabled` | Mixin applied to the container when it's disabled | `{}` +`--paper-input-container-label` | Mixin applied to the label | `{}` +`--paper-input-container-label-focus` | Mixin applied to the label when the input is focused | `{}` +`--paper-input-container-input` | Mixin applied to the input | `{}` +`--paper-input-container-underline` | Mixin applied to the underline | `{}` +`--paper-input-container-underline-focus` | Mixin applied to the underline when the input is focued | `{}` +`--paper-input-container-underline-disabled` | Mixin applied to the underline when the input is disabled | `{}` +`--paper-input-prefix` | Mixin applied to the input prefix | `{}` +`--paper-input-suffix` | Mixin applied to the input suffix | `{}` + +This element is `display:block` by default, but you can set the `inline` attribute to make it +`display:inline-block`. + + +##<paper-input-error> + + +`<paper-input-error>` is an error message for use with `<paper-input-container>`. The error is +displayed when the `<paper-input-container>` is `invalid`. + + <paper-input-container> + <input is="iron-input" pattern="[0-9]*"> + <paper-input-error>Only numbers are allowed!</paper-input-error> + </paper-input-container> + +### Styling + +The following custom properties and mixins are available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-input-container-invalid-color` | The foreground color of the error | `--google-red-500` +`--paper-input-error` | Mixin applied to the error | `{}` + + +##<paper-textarea> + + +`<paper-textarea>` is a multi-line text field with Material Design styling. + + <paper-textarea label="Textarea label"></paper-textarea> + +See `Polymer.PaperInputBehavior` for more API docs. + +### Validation + +Currently only `required` and `maxlength` validation is supported. + +### Styling + +See `Polymer.PaperInputContainer` for a list of custom properties used to +style this element. + + +##Polymer.PaperInputBehavior + + +Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-container>`. This +behavior is implemented by `<paper-input>`. It exposes a number of properties from +`<paper-input-container>` and `<input is="iron-input">` and they should be bound in your +template. + +The input element can be accessed by the `inputElement` property if you need to access +properties or methods that are not exposed. + + +##Polymer.PaperInputAddonBehavior + + +Use `Polymer.PaperInputAddonBehavior` to implement an add-on for `<paper-input-container>`. A +add-on appears below the input, and may display information based on the input value and +validity such as a character counter or an error message. +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/bower.json b/third_party/polymer/v1_0/components-chromium/paper-input/bower.json index 09aace46..e725697 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-input/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-input", - "version": "1.0.18", + "version": "1.1.1", "description": "Material design text fields", "authors": [ "The Polymer Authors" @@ -27,7 +27,7 @@ "homepage": "https://github.com/PolymerElements/paper-input", "ignore": [], "dependencies": { - "polymer": "Polymer/polymer#^1.2.0", + "polymer": "Polymer/polymer#^1.1.0", "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^1.0.0", "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0", "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#^1.0.0", @@ -35,13 +35,13 @@ "paper-styles": "PolymerElements/paper-styles#^1.0.0" }, "devDependencies": { - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "Polymer/web-component-tester#^3.3.0", - "test-fixture": "PolymerElements/test-fixture#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-icon": "PolymerElements/iron-icon#^1.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0", - "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0" + "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", + "test-fixture": "PolymerElements/test-fixture#^1.0.0", + "web-component-tester": "Polymer/web-component-tester#^3.3.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-behavior-extracted.js index fc225a47..24ab743 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-behavior-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-behavior-extracted.js
@@ -296,6 +296,11 @@ _ariaDescribedBy: { type: String, value: '' + }, + + _ariaLabelledBy: { + type: String, + value: '' } },
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-char-counter.html b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-char-counter.html index 786b580..a19b432 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-char-counter.html +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-char-counter.html
@@ -7,7 +7,7 @@ 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"> +<link rel="import" href="../paper-styles/typography.html"> <link rel="import" href="paper-input-addon-behavior.html"> <!--
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container-extracted.js index 731dd48a..420007d 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container-extracted.js
@@ -142,21 +142,6 @@ } else { this._handleValue(this._inputElement); } - - this._numberOfPrefixNodes = 0; - this._prefixObserver = Polymer.dom(this.$.prefix).observeNodes( - function(mutations) { - // Keep track whether there's at least one prefix node, since it - // affects laying out the floating label. - this._numberOfPrefixNodes += mutations.addedNodes.length - - mutations.removedNodes.length; - }.bind(this)); - }, - - detached: function() { - if (this._prefixObserver) { - Polymer.dom(this.$.prefix).unobserveNodes(this._prefixObserver); - } }, _onAddonAttached: function(event) { @@ -248,16 +233,15 @@ if (alwaysFloatLabel || _inputHasContent) { cls += ' label-is-floating'; + // If the label is floating, ignore any offsets that may have been + // applied from a prefix element. + this.$.labelAndInputContainer.style.position = 'static'; + if (invalid) { cls += ' is-invalid'; } else if (focused) { cls += " label-is-highlighted"; } - // If a prefix element exists, the label has a horizontal offset - // which needs to be undone when displayed as a floating label. - if (this._numberOfPrefixNodes > 0) { - this.$.labelAndInputContainer.style.position = 'static'; - } } else { // When the label is not floating, it should overlap the input element. if (label) {
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html index f81035f..9c32f77 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html
@@ -7,7 +7,10 @@ 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"> +<link rel="import" href="../paper-styles/color.html"> +<link rel="import" href="../paper-styles/typography.html"> +<link rel="import" href="../paper-styles/default-theme.html"> +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <!-- `<paper-input-container>` is a container for a `<label>`, an `<input is="iron-input">` or @@ -118,6 +121,7 @@ .focused-line { height: 2px; + @apply(--layout-fit); -webkit-transform-origin: center center; transform-origin: center center; @@ -151,6 +155,7 @@ .unfocused-line { height: 1px; + @apply(--layout-fit); background: var(--paper-input-container-color, --secondary-text-color); @apply(--paper-input-container-underline); @@ -298,8 +303,8 @@ </div> <div class$="[[_computeUnderlineClass(focused,invalid)]]"> - <div class="unfocused-line fit"></div> - <div class="focused-line fit"></div> + <div class="unfocused-line"></div> + <div class="focused-line"></div> </div> <div class$="[[_computeAddOnContentClass(focused,invalid)]]">
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error.html b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error.html index 057fdb3..c00f52c 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error.html +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-error.html
@@ -7,7 +7,8 @@ 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"> +<link rel="import" href="../paper-styles/color.html"> +<link rel="import" href="../paper-styles/typography.html"> <link rel="import" href="paper-input-addon-behavior.html"> <!--
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input.html b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input.html index 8836117..584237e 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input.html +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input.html
@@ -7,12 +7,12 @@ 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="../iron-form-element-behavior/iron-form-element-behavior.html"> +<link rel="import" href="../iron-input/iron-input.html"> <link rel="import" href="paper-input-behavior.html"> +<link rel="import" href="paper-input-char-counter.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"> <!-- Material design: [Text fields](https://www.google.com/design/spec/components/text-fields.html)
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-textarea.html b/third_party/polymer/v1_0/components-chromium/paper-input/paper-textarea.html index 22295743..207f12bb 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-textarea.html +++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-textarea.html
@@ -9,9 +9,9 @@ --><html><head><link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../iron-autogrow-textarea/iron-autogrow-textarea.html"> <link rel="import" href="paper-input-behavior.html"> +<link rel="import" href="paper-input-char-counter.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-textarea>` is a multi-line text field with Material Design styling.
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-item/.bower.json index 657aa463..8031b12 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-item/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-item", - "version": "1.0.6", + "version": "1.1.1", "description": "A material-design styled list item", "authors": [ "The Polymer Authors" @@ -26,6 +26,7 @@ "dependencies": { "polymer": "Polymer/polymer#^1.1.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", "iron-behaviors": "polymerelements/iron-behaviors#^1.0.0" }, "devDependencies": { @@ -34,16 +35,18 @@ "iron-icons": "PolymerElements/iron-icons#^1.0.0", "paper-checkbox": "PolymerElements/paper-checkbox#^1.0.0", "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", + "paper-input": "PolymerElements/paper-input#^1.0.0", "paper-toggle-button": "PolymerElements/paper-toggle-button#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "Polymer/web-component-tester#^3.3.0", - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" + "web-component-tester": "Polymer/web-component-tester#^3.4.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0" }, - "_release": "1.0.6", + "_release": "1.1.1", "_resolution": { "type": "version", - "tag": "v1.0.6", - "commit": "803078d9942d1279fb6f4142b7522186d57f17c8" + "tag": "v1.1.1", + "commit": "ca1a8afea954b80c839c6cdeef0bc88b9296dd1d" }, "_source": "git://github.com/PolymerElements/paper-item.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/.travis.yml b/third_party/polymer/v1_0/components-chromium/paper-item/.travis.yml deleted file mode 100644 index 8be788d8..0000000 --- a/third_party/polymer/v1_0/components-chromium/paper-item/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: NCk3KK+wbaXMzp8XAY6FeL+TSdI0AlPI3/tl0OpsUIaU2EiCjQuzf/UpyzCW5XZMEVFF4q/eDjrPkqJodHfpngj36mpkfmfqj9DrgDmYsV9BDvsTd8KmLsA6H8D6p7Qer+r1JMMB8PvX44vdhQ6GhZD1HFNYK1Ekpt0TkYwWKNw= - - secure: TGgUEQe6FJS+GuYk94d//8YQmDLUu0ekMvPSIs8TQ2QkdBK4SL+2bSXZt44BbDEOwc9P4NCPSUx/RMiCAqsc5OGRJImzb/zqPNIDTeKG6q72HPBBBD3Sk0CrEpTQbOK/Flaa/B7RYR0U1kuljSmRS7lPG19nnY8gOHnIAgwIyk0=
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/README.md b/third_party/polymer/v1_0/components-chromium/paper-item/README.md index 95cd919..417073f 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-item/README.md
@@ -2,13 +2,15 @@ <!--- This README is automatically generated from the comments in these files: -all-imports.html paper-icon-item.html paper-item-body.html paper-item-shared-styles.html paper-item.html +paper-icon-item.html paper-item-body.html paper-item.html Edit those files, and our readme bot will duplicate them over here! Edit this file, and the bot will squash your changes :) --> +[](https://travis-ci.org/PolymerElements/paper-item) + _[Demo and API Docs](https://elements.polymer-project.org/elements/paper-item)_
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/bower.json b/third_party/polymer/v1_0/components-chromium/paper-item/bower.json index 57850c68..04f09d9 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-item/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-item", - "version": "1.0.6", + "version": "1.1.1", "description": "A material-design styled list item", "authors": [ "The Polymer Authors" @@ -26,6 +26,7 @@ "dependencies": { "polymer": "Polymer/polymer#^1.1.0", "paper-styles": "PolymerElements/paper-styles#^1.0.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", "iron-behaviors": "polymerelements/iron-behaviors#^1.0.0" }, "devDependencies": { @@ -34,9 +35,11 @@ "iron-icons": "PolymerElements/iron-icons#^1.0.0", "paper-checkbox": "PolymerElements/paper-checkbox#^1.0.0", "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", + "paper-input": "PolymerElements/paper-input#^1.0.0", "paper-toggle-button": "PolymerElements/paper-toggle-button#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "web-component-tester": "Polymer/web-component-tester#^3.3.0", - "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" + "web-component-tester": "Polymer/web-component-tester#^3.4.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item-extracted.js index 6b5eb2a..a8b2d609 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item-extracted.js
@@ -1,13 +1,7 @@ Polymer({ is: 'paper-icon-item', - hostAttributes: { - 'role': 'option', - 'tabindex': '0' - }, - behaviors: [ - Polymer.IronControlState, - Polymer.IronButtonState + Polymer.PaperItemBehavior ] }); \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item.html b/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item.html index 48ba711..95583ed 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item.html +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item.html
@@ -9,11 +9,13 @@ --><html><head><link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../iron-behaviors/iron-control-state.html"> <link rel="import" href="../iron-behaviors/iron-button-state.html"> -<link rel="import" href="../paper-styles/paper-styles.html"> +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../paper-styles/typography.html"> +<link rel="import" href="paper-item-behavior.html"> <link rel="import" href="paper-item-shared-styles.html"> <!-- -`<paper-icon-item>` is a convenience element to make an item with icon. It is a non interactive list +`<paper-icon-item>` is a convenience element to make an item with icon. It is an interactive list item with a fixed-width icon area, according to Material Design. This is useful if the icons are of varying widths, but you want the item bodies to line up. Use this like a `<paper-item>`. The child node with the attribute `item-icon` is placed in the icon area. @@ -41,7 +43,6 @@ `--paper-item-disabled` | Mixin applied to disabled paper-items | `{}` `--paper-item-focused` | Mixin applied to focused paper-items | `{}` `--paper-item-focused-before` | Mixin applied to :before focused paper-items | `{}` - --> </head><body><dom-module id="paper-icon-item"> @@ -59,10 +60,12 @@ .content-icon { width: var(--paper-item-icon-width, 56px); + @apply(--layout-horizontal); + @apply(--layout-center); } </style> - <div id="contentIcon" class="content-icon layout horizontal center"> + <div id="contentIcon" class="content-icon"> <content select="[item-icon]"></content> </div> <content></content>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior-extracted.js new file mode 100644 index 0000000..da24431 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior-extracted.js
@@ -0,0 +1,14 @@ +/** @polymerBehavior Polymer.PaperItemBehavior */ + Polymer.PaperItemBehaviorImpl = { + hostAttributes: { + role: 'option', + tabindex: '0' + } + }; + + /** @polymerBehavior */ + Polymer.PaperItemBehavior = [ + Polymer.IronControlState, + Polymer.IronButtonState, + Polymer.PaperItemBehaviorImpl + ]; \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior.html b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior.html new file mode 100644 index 0000000..c90e5c6c --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior.html
@@ -0,0 +1,19 @@ +<!-- +@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-control-state.html"> +<link rel="import" href="../iron-behaviors/iron-button-state.html"> + +<!-- +`PaperItemBehavior` is a convenience behavior shared by <paper-item> and +<paper-icon-item> that manages the shared control states and attributes of +the items. +--> + +</head><body><script src="paper-item-behavior-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-body.html b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-body.html index f83106c4..ea73d4f 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-body.html +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-body.html
@@ -7,8 +7,9 @@ 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"> - +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../paper-styles/default-theme.html"> +<link rel="import" href="../paper-styles/typography.html"> <!-- Use `<paper-item-body>` in a `<paper-item>` or `<paper-icon-item>` to make two- or three- line items. It is a flex item that is a vertical flexbox.
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-extracted.js index e554a24..0386a2a 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-extracted.js
@@ -1,13 +1,7 @@ Polymer({ is: 'paper-item', - hostAttributes: { - role: 'option', - tabindex: '0' - }, - behaviors: [ - Polymer.IronControlState, - Polymer.IronButtonState + Polymer.PaperItemBehavior ] }); \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-shared-styles.html b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-shared-styles.html index 0bc190d..25fe1340 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-shared-styles.html +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item-shared-styles.html
@@ -38,6 +38,7 @@ content: ''; background: currentColor; opacity: var(--dark-divider-opacity); + pointer-events: none; @apply(--paper-item-focused-before); }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item.html b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item.html index 1496694..f6a4b60 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-item/paper-item.html +++ b/third_party/polymer/v1_0/components-chromium/paper-item/paper-item.html
@@ -9,13 +9,15 @@ --><html><head><link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../iron-behaviors/iron-control-state.html"> <link rel="import" href="../iron-behaviors/iron-button-state.html"> -<link rel="import" href="../paper-styles/paper-styles.html"> +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../paper-styles/default-theme.html"> +<link rel="import" href="paper-item-behavior.html"> <link rel="import" href="paper-item-shared-styles.html"> <!-- Material design: [Lists](https://www.google.com/design/spec/components/lists.html) -`<paper-item>` is a non-interactive list item. By default, it is a horizontal flexbox. +`<paper-item>` is an interactive list item. By default, it is a horizontal flexbox. <paper-item>Item</paper-item> @@ -45,7 +47,6 @@ `--paper-item-focused` | Mixin applied to focused paper-items | `{}` `--paper-item-focused-before` | Mixin applied to :before focused paper-items | `{}` - ### Accessibility This element has `role="listitem"` by default. Depending on usage, it may be more appropriate to set
diff --git a/third_party/polymer/v1_0/components-chromium/paper-material/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-material/.bower.json index 0474530..b602394 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-material/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-material/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-material", - "version": "1.0.3", + "version": "1.0.4", "description": "A material design container that looks like a lifted sheet of paper", "private": true, "authors": [ @@ -13,9 +13,7 @@ "paper", "container" ], - "main": [ - "paper-material.html" - ], + "main": "paper-material.html", "repository": { "type": "git", "url": "git://github.com/PolymerElements/paper-material" @@ -29,15 +27,15 @@ }, "devDependencies": { "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0" }, - "_release": "1.0.3", + "_release": "1.0.4", "_resolution": { "type": "version", - "tag": "v1.0.3", - "commit": "2e99c0754edb817518f59313d2533ccc2e1ab82a" + "tag": "v1.0.4", + "commit": "05f3800d37f8c5cad63ac2cf279f01bffb7d4fe8" }, "_source": "git://github.com/PolymerElements/paper-material.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-material/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-material/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-material/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-material/README.md b/third_party/polymer/v1_0/components-chromium/paper-material/README.md index 1105102..31ebed6 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-material/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-material/README.md
@@ -1,13 +1,31 @@ -# paper-material -A Material Design container that looks like a lifted piece of paper. + +<!--- + +This README is automatically generated from the comments in these files: +paper-material.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-material) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-material)_ + + +##<paper-material> + + +Material design: [Cards](https://www.google.com/design/spec/components/cards.html) `paper-material` is a container that renders two shadows on top of each other to create the effect of a lifted piece of paper. Example: -```html -<paper-material elevation="1"> - ... content ... -</paper-material> -``` + <paper-material elevation="1"> + ... content ... + </paper-material> + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-material/bower.json b/third_party/polymer/v1_0/components-chromium/paper-material/bower.json index 42d0c186..296b062 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-material/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-material/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-material", - "version": "1.0.3", + "version": "1.0.4", "description": "A material design container that looks like a lifted sheet of paper", "private": true, "authors": [ @@ -13,9 +13,7 @@ "paper", "container" ], - "main": [ - "paper-material.html" - ], + "main": "paper-material.html", "repository": { "type": "git", "url": "git://github.com/PolymerElements/paper-material" @@ -29,7 +27,7 @@ }, "devDependencies": { "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", "iron-component-page": "PolymerElements/iron-component-page#^1.0.0" }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-menu/.bower.json index cc1584b..f28917c 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-menu", - "version": "1.1.1", + "version": "1.2.0", "description": "Implements an accessible material design menu", "authors": "The Polymer Authors", "keywords": [ @@ -21,25 +21,26 @@ "homepage": "https://github.com/PolymerElements/paper-menu", "ignore": [], "dependencies": { - "iron-menu-behavior": "PolymerElements/iron-menu-behavior#^1.0.0", - "paper-styles": "PolymerElements/paper-styles#^1.0.0", - "iron-collapse": "PolymerElements/iron-collapse#^1.0.0", + "polymer": "Polymer/polymer#^1.1.0", "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0", - "polymer": "Polymer/polymer#^1.0.0" + "iron-collapse": "PolymerElements/iron-collapse#^1.0.0", + "iron-menu-behavior": "PolymerElements/iron-menu-behavior#^1.0.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "paper-styles": "PolymerElements/paper-styles#^1.0.0" }, "devDependencies": { "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "paper-item": "PolymerElements/paper-item#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "web-component-tester": "*", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, - "_release": "1.1.1", + "_release": "1.2.0", "_resolution": { "type": "version", - "tag": "v1.1.1", - "commit": "a09d2b6fd3dbb9f588297fda7a1448499c6d7e4f" + "tag": "v1.2.0", + "commit": "c5f184ce4f337912deae53b345a4260f333f5412" }, "_source": "git://github.com/PolymerElements/paper-menu.git", "_target": "^1.1.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-menu/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/README.md b/third_party/polymer/v1_0/components-chromium/paper-menu/README.md index 9991680..a4d88d5 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/README.md
@@ -1,3 +1,104 @@ -# paper-menu -`<paper-menu>` implements an accessible menu control with Material Design styling. +<!--- + +This README is automatically generated from the comments in these files: +paper-menu.html paper-submenu.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-menu) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-menu)_ + + +##<paper-menu> + + +Material design: [Menus](https://www.google.com/design/spec/components/menus.html) + +`<paper-menu>` implements an accessible menu control with Material Design styling. The focused item +is highlighted, and the selected item has bolded text. + + <paper-menu> + <paper-item>Item 1</paper-item> + <paper-item>Item 2</paper-item> + </paper-menu> + +An initial selection can be specified with the `selected` attribute. + + <paper-menu selected="0"> + <paper-item>Item 1</paper-item> + <paper-item>Item 2</paper-item> + </paper-menu> + +Make a multi-select menu with the `multi` attribute. Items in a multi-select menu can be deselected, +and multiple item can be selected. + + <paper-menu multi> + <paper-item>Item 1</paper-item> + <paper-item>Item 2</paper-item> + </paper-menu> + +### Styling + +The following custom properties and mixins are available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-menu-background-color` | Menu background color | `--primary-background-color` +`--paper-menu-color` | Menu foreground color | `--primary-text-color` +`--paper-menu-disabled-color` | Foreground color for a disabled item | `--disabled-text-color` +`--paper-menu` | Mixin applied to the menu | `{}` +`--paper-menu-selected-item` | Mixin applied to the selected item | `{}` +`--paper-menu-focused-item` | Mixin applied to the focused item | `{}` +`--paper-menu-focused-item-after` | Mixin applied to the ::after pseudo-element for the focused item | `{}` + +### Accessibility + +`<paper-menu>` has `role="menu"` by default. A multi-select menu will also have +`aria-multiselectable` set. It implements key bindings to navigate through the menu with the up and +down arrow keys, esc to exit the menu, and enter to activate a menu item. Typing the first letter +of a menu item will also focus it. + + + +##<paper-submenu> + + +`<paper-submenu>` is a nested menu inside of a parent `<paper-menu>`. It +consists of a trigger that expands or collapses another `<paper-menu>`: + + <paper-menu> + <paper-submenu> + <paper-item class="menu-trigger">Topics</paper-item> + <paper-menu class="menu-content"> + <paper-item>Topic 1</paper-item> + <paper-item>Topic 2</paper-item> + <paper-item>Topic 3</paper-item> + </paper-menu> + </paper-submenu> + <paper-submenu> + <paper-item class="menu-trigger">Faves</paper-item> + <paper-menu class="menu-content"> + <paper-item>Fave 1</paper-item> + <paper-item>Fave 2</paper-item> + </paper-menu> + </paper-submenu> + <paper-submenu disabled> + <paper-item class="menu-trigger">Unavailable</paper-item> + <paper-menu class="menu-content"> + <paper-item>Disabled 1</paper-item> + <paper-item>Disabled 2</paper-item> + </paper-menu> + </paper-submenu> + </paper-menu> + +Just like in `<paper-menu>`, the focused item is highlighted, and the selected +item has bolded text. Please see the `<paper-menu>` docs for which attributes +(such as `multi` and `selected`), and styling options are available for the +`menu-content` menu. + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/bower.json b/third_party/polymer/v1_0/components-chromium/paper-menu/bower.json index 55ef37fd..deff00e 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-menu", - "version": "1.1.1", + "version": "1.2.0", "description": "Implements an accessible material design menu", "authors": "The Polymer Authors", "keywords": [ @@ -21,17 +21,18 @@ "homepage": "https://github.com/PolymerElements/paper-menu", "ignore": [], "dependencies": { - "iron-menu-behavior": "PolymerElements/iron-menu-behavior#^1.0.0", - "paper-styles": "PolymerElements/paper-styles#^1.0.0", - "iron-collapse": "PolymerElements/iron-collapse#^1.0.0", + "polymer": "Polymer/polymer#^1.1.0", "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0", - "polymer": "Polymer/polymer#^1.0.0" + "iron-collapse": "PolymerElements/iron-collapse#^1.0.0", + "iron-menu-behavior": "PolymerElements/iron-menu-behavior#^1.0.0", + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "paper-styles": "PolymerElements/paper-styles#^1.0.0" }, "devDependencies": { "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "paper-item": "PolymerElements/paper-item#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", - "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0", "web-component-tester": "*", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-extracted.js index a654560..6c9410f 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-extracted.js
@@ -1,13 +1,9 @@ (function() { + Polymer({ + is: 'paper-menu', - Polymer({ - - is: 'paper-menu', - - behaviors: [ - Polymer.IronMenuBehavior - ] - - }); - -})(); \ No newline at end of file + behaviors: [ + Polymer.IronMenuBehavior + ] + }); + })(); \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared-styles.html b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared-styles.html new file mode 100644 index 0000000..680655e1 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared-styles.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 +--> + +<dom-module id="paper-menu-shared-styles"> + <template> + <style> + /* need a wrapper element to make this higher specificity than the :host rule in paper-item */ + .selectable-content > ::content > .iron-selected { + font-weight: bold; + + @apply(--paper-menu-selected-item); + } + + .selectable-content > ::content > [disabled] { + color: var(--paper-menu-disabled-color, --disabled-text-color); + } + + .selectable-content > ::content > *:focus { + position: relative; + outline: 0; + + @apply(--paper-menu-focused-item); + } + + .selectable-content > ::content > *:focus:after { + @apply(--layout-fit); + background: currentColor; + opacity: var(--dark-divider-opacity); + content: ''; + + @apply(--paper-menu-focused-item-after); + } + + .selectable-content > ::content > *[colored]:focus:after { + opacity: 0.26; + } + </style> + </template> +</dom-module>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared.css b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared.css deleted file mode 100644 index e76a368..0000000 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared.css +++ /dev/null
@@ -1,40 +0,0 @@ -/** -@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 -*/ - -/* need a wrapper element to make this higher specificity than the :host rule in paper-item */ -.selectable-content > ::content > .iron-selected { - font-weight: bold; - - @apply(--paper-menu-selected-item); -} - -.selectable-content > ::content > [disabled] { - color: var(--paper-menu-disabled-color, --disabled-text-color); -} - -.selectable-content > ::content > *:focus { - position: relative; - outline: 0; - - @apply(--paper-menu-focused-item); -} - -.selectable-content > ::content > *:focus:after { - @apply(--layout-fit); - background: currentColor; - opacity: var(--dark-divider-opacity); - content: ''; - - @apply(--paper-menu-focused-item-after); -} - -.selectable-content > ::content > *[colored]:focus:after { - opacity: 0.26; -}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu.html b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu.html index cceef31a..c9bda353 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu.html +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu.html
@@ -7,10 +7,14 @@ 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-flex-layout/iron-flex-layout.html"> <link rel="import" href="../iron-menu-behavior/iron-menu-behavior.html"> -<link rel="import" href="../paper-styles/paper-styles.html"> +<link rel="import" href="../paper-styles/default-theme.html"> +<link rel="import" href="paper-menu-shared-styles.html"> <!-- +Material design: [Menus](https://www.google.com/design/spec/components/menus.html) + `<paper-menu>` implements an accessible menu control with Material Design styling. The focused item is highlighted, and the selected item has bolded text. @@ -41,7 +45,7 @@ Custom property | Description | Default ----------------|-------------|---------- `--paper-menu-background-color` | Menu background color | `--primary-background-color` -`--paper-menu-color` | Menu foreground color | `--primary-text-color` +`--paper-menu-color` | Menu foreground color | `--primary-text-color` `--paper-menu-disabled-color` | Foreground color for a disabled item | `--disabled-text-color` `--paper-menu` | Mixin applied to the menu | `{}` `--paper-menu-selected-item` | Mixin applied to the selected item | `{}` @@ -62,27 +66,24 @@ --> </head><body><dom-module id="paper-menu"> - <link rel="import" type="css" href="paper-menu-shared.css"> - - <style> - :host { - display: block; - padding: 8px 0; - - background: var(--paper-menu-background-color, --primary-background-color); - color: var(--paper-menu-color, --primary-text-color); - - @apply(--paper-menu); - } - </style> <template> + <style include="paper-menu-shared-styles"></style> + <style> + :host { + display: block; + padding: 8px 0; + + background: var(--paper-menu-background-color, --primary-background-color); + color: var(--paper-menu-color, --primary-text-color); + + @apply(--paper-menu); + } + </style> <div class="selectable-content"> <content></content> </div> - </template> -</dom-module> - + </dom-module> <script src="paper-menu-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu-extracted.js index eb50ecc..816cfdd 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu-extracted.js
@@ -1,131 +1,127 @@ (function() { + Polymer({ + is: 'paper-submenu', - Polymer({ + properties: { + /** + * Fired when the submenu is opened. + * + * @event paper-submenu-open + */ - is: 'paper-submenu', + /** + * Fired when the submenu is closed. + * + * @event paper-submenu-close + */ - properties: { - /** - * Fired when the submenu is opened. - * - * @event paper-submenu-open - */ + /** + * Set opened to true to show the collapse element and to false to hide it. + * + * @attribute opened + */ + opened: { + type: Boolean, + value: false, + notify: true, + observer: '_openedChanged' + } + }, - /** - * Fired when the submenu is closed. - * - * @event paper-submenu-close - */ + behaviors: [ + Polymer.IronControlState + ], - /** - * Set opened to true to show the collapse element and to false to hide it. - * - * @attribute opened - */ - opened: { - type: Boolean, - value: false, - notify: true, - observer: '_openedChanged' - } - }, + get __parent() { + return Polymer.dom(this).parentNode; + }, - behaviors: [ - Polymer.IronControlState - ], + get __trigger() { + return Polymer.dom(this.$.trigger).getDistributedNodes()[0]; + }, - get __parent() { - return Polymer.dom(this).parentNode; - }, + attached: function() { + this.listen(this.__parent, 'iron-activate', '_onParentIronActivate'); + }, - get __trigger() { - return Polymer.dom(this.$.trigger).getDistributedNodes()[0]; - }, + dettached: function() { + this.unlisten(this.__parent, 'iron-activate', '_onParentIronActivate'); + }, - attached: function() { - this.listen(this.__parent, 'iron-activate', '_onParentIronActivate'); - }, + /** + * Expand the submenu content. + */ + open: function() { + if (this.disabled) + return; + this.$.collapse.show(); + this._active = true; + this.__trigger.classList.add('iron-selected'); + }, - dettached: function() { - this.unlisten(this.__parent, 'iron-activate', '_onParentIronActivate'); - }, + /** + * Collapse the submenu content. + */ + close: function() { + this.$.collapse.hide(); + this._active = false; + this.__trigger.classList.remove('iron-selected'); + }, - /** - * Expand the submenu content. - */ - open: function() { - if (this.disabled) - return; - this.$.collapse.show(); - this._active = true; - this.__trigger.classList.add('iron-selected'); - }, + /** + * A handler that is called when the trigger is tapped. + */ + _onTap: function() { + if (this.disabled) + return; + this.$.collapse.toggle(); + }, - /** - * Collapse the submenu content. - */ - close: function() { - this.$.collapse.hide(); - this._active = false; - this.__trigger.classList.remove('iron-selected'); - }, + /** + * Toggles the submenu content when the trigger is tapped. + */ + _openedChanged: function(opened, oldOpened) { + if (opened) { + this.fire('paper-submenu-open'); + } else if (oldOpened != null) { + this.fire('paper-submenu-close'); + } + }, - /** - * A handler that is called when the trigger is tapped. - */ - _onTap: function() { - if (this.disabled) - return; - this.$.collapse.toggle(); - }, + /** + * A handler that is called when `iron-activate` is fired. + * + * @param {CustomEvent} event An `iron-activate` event. + */ + _onParentIronActivate: function(event) { + if (Polymer.Gestures.findOriginalTarget(event) !== this.__parent) { + return; + } - /** - * Toggles the submenu content when the trigger is tapped. - */ - _openedChanged: function(opened, oldOpened) { - if (opened) { - this.fire('paper-submenu-open'); - } else if (oldOpened != null) { - this.fire('paper-submenu-close'); - } - }, + // The activated item can either be this submenu, in which case it + // should be expanded, or any of the other sibling submenus, in which + // case this submenu should be collapsed. + if (event.detail.item == this) { + if (this._active) + return; + this.open(); + } else { + this.close(); + } + }, - /** - * A handler that is called when `iron-activate` is fired. - * - * @param {CustomEvent} event An `iron-activate` event. - */ - _onParentIronActivate: function(event) { - if (Polymer.Gestures.findOriginalTarget(event) !== this.__parent) { - return; - } + /** + * If the dropdown is open when disabled becomes true, close the + * dropdown. + * + * @param {boolean} disabled True if disabled, otherwise false. + */ + _disabledChanged: function(disabled) { + Polymer.IronControlState._disabledChanged.apply(this, arguments); + if (disabled && this._active) { + this.close(); - // The activated item can either be this submenu, in which case it - // should be expanded, or any of the other sibling submenus, in which - // case this submenu should be collapsed. - if (event.detail.item == this) { - if (this._active) - return; - this.open(); - } else { - this.close(); - } - }, - - /** - * If the dropdown is open when disabled becomes true, close the - * dropdown. - * - * @param {boolean} disabled True if disabled, otherwise false. - */ - _disabledChanged: function(disabled) { - Polymer.IronControlState._disabledChanged.apply(this, arguments); - if (disabled && this._active) { - this.close(); - - } - } - - }); - -})(); \ No newline at end of file + } + } + }); + })(); \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu.html b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu.html index e3bffb9c..3fe5a7d 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu.html +++ b/third_party/polymer/v1_0/components-chromium/paper-menu/paper-submenu.html
@@ -10,7 +10,9 @@ <link rel="import" href="../iron-menu-behavior/iron-menu-behavior.html"> <link rel="import" href="../iron-behaviors/iron-control-state.html"> <link rel="import" href="../iron-collapse/iron-collapse.html"> -<link rel="import" href="../paper-styles/paper-styles.html"> +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="../paper-styles/default-theme.html"> +<link rel="import" href="paper-menu-shared-styles.html"> <!-- `<paper-submenu>` is a nested menu inside of a parent `<paper-menu>`. It @@ -53,9 +55,9 @@ --> </head><body><dom-module id="paper-submenu"> - <link rel="import" type="css" href="paper-menu-shared.css"> - <template> + <style include="paper-menu-shared-styles"></style> + <div class="selectable-content" on-tap="_onTap"> <content id="trigger" select=".menu-trigger"></content> </div> @@ -64,6 +66,5 @@ </iron-collapse> </template> -</dom-module> - + </dom-module> <script src="paper-submenu-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-radio-button/.travis.yml b/third_party/polymer/v1_0/components-chromium/paper-radio-button/.travis.yml deleted file mode 100644 index 6b091474..0000000 --- a/third_party/polymer/v1_0/components-chromium/paper-radio-button/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: P6B/39IMzhm/jBmxD+0CDZEPYNMMaizAgpn4MXUUlAmmdMJNwovzvm/kYtVyoPfGiJ08NJh5tNRLQbkG12OH71lQ7ReTiru0hEy93ssmIh0U6ZUAAxTZVQ9SxB5gjrQU8/0fVJ9tNd0kBklHH4FoK+ZtJurhKLJaXhXsupXpcuI= - - secure: rxY6LCY199Lt1aRGK8Hpq3wjx8xcpb91x21fJStKROlpJTlfp+c0yevK1oYkklzChJWEFewFNTYlHbm9pc7TCyXK2WCR0v1GgSeJAUpP4TONkdpueeOvsVC/CGB9mIXEtfUEh2CCdWDj+D7JGLdUvbgmu8C3gfqfP+AyXbQt5Jc=
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-ripple/.bower.json index fc500c1..157225e 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-ripple/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-ripple/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-ripple", - "version": "1.0.4", + "version": "1.0.5", "license": "http://polymer.github.io/LICENSE.txt", "description": "Adds a material design ripple to any container", "private": true, @@ -27,16 +27,17 @@ "iron-icons": "polymerelements/iron-icons#^1.0.0", "paper-styles": "polymerelements/paper-styles#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/paper-ripple", - "_release": "1.0.4", + "_release": "1.0.5", "_resolution": { "type": "version", - "tag": "v1.0.4", - "commit": "5f5893ca7bd6a8413d2f777c092a1a179b6bd45e" + "tag": "v1.0.5", + "commit": "d72e7a9a8ab518b901ed18dde492df3b87a93be5" }, "_source": "git://github.com/PolymerElements/paper-ripple.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-ripple/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-ripple/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/README.md b/third_party/polymer/v1_0/components-chromium/paper-ripple/README.md index b9bde23..9e4c8ca 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-ripple/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-ripple/README.md
@@ -1,5 +1,23 @@ -paper-ripple -============ + +<!--- + +This README is automatically generated from the comments in these files: +paper-ripple.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-ripple) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-ripple)_ + + +##<paper-ripple> + + +Material design: [Surface reaction](https://www.google.com/design/spec/animation/responsive-interaction.html#responsive-interaction-surface-reaction) `paper-ripple` provides a visual effect that other paper elements can use to simulate a rippling effect emanating from the point of contact. The @@ -7,59 +25,52 @@ Example: -```html -<paper-ripple></paper-ripple> -``` + <div style="position:relative"> + <paper-ripple></paper-ripple> + </div> + +Note, it's important that the parent container of the ripple be relative position, otherwise +the ripple will emanate outside of the desired container. `paper-ripple` listens to "mousedown" and "mouseup" 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. +important if you call `downAction()` you will have to make sure to call +`upAction()` so that `paper-ripple` would end the animation loop. Example: -```html -<paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> -... -<script> - downAction: function(e) { - this.$.ripple.downAction({x: e.x, y: e.y}); - }, - upAction: function(e) { - this.$.ripple.upAction(); - } -</script> -``` + <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: + Use CSS color property to style the ripple: -```css -paper-ripple { - color: #4285f4; -} -``` + 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. + 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. -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> -```html -<paper-ripple recenters></paper-ripple> -``` +You can also center the ripple inside its container from the start. -Apply `center` to center the ripple inside its container from the start. - -```html -<paper-ripple center></paper-ripple> -``` + <paper-ripple center></paper-ripple> Apply `circle` class to make the rippling effect within a circle. -```html -<paper-ripple class="circle"></paper-ripple> -``` + <paper-ripple class="circle"></paper-ripple> + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/bower.json b/third_party/polymer/v1_0/components-chromium/paper-ripple/bower.json index f0504368..2190e22 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-ripple/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-ripple/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-ripple", - "version": "1.0.4", + "version": "1.0.5", "license": "http://polymer.github.io/LICENSE.txt", "description": "Adds a material design ripple to any container", "private": true, @@ -27,8 +27,9 @@ "iron-icons": "polymerelements/iron-icons#^1.0.0", "paper-styles": "polymerelements/paper-styles#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/index.html b/third_party/polymer/v1_0/components-chromium/paper-ripple/index.html index 3c371fa..e552b0b 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-ripple/index.html +++ b/third_party/polymer/v1_0/components-chromium/paper-ripple/index.html
@@ -2,11 +2,11 @@ <!-- @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 +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 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <html> <head>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js index 2fc2c24..b5b233b 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js
@@ -399,10 +399,6 @@ } }, - observers: [ - '_noinkChanged(noink, isAttached)' - ], - get target () { var ownerRoot = Polymer.dom(this).getOwnerRoot(); var target; @@ -423,6 +419,10 @@ }, attached: function() { + // Set up a11yKeysBehavior to listen to key events on the target, + // so that space and enter activate the ripple even if the target doesn't + // handle key events. The key handlers deal with `noink` themselves. + this.keyEventTarget = this.target; this.listen(this.target, 'up', 'uiUpAction'); this.listen(this.target, 'down', 'uiDownAction'); }, @@ -592,12 +592,6 @@ } else { this.upAction(); } - }, - - _noinkChanged: function(noink, attached) { - if (attached) { - this.keyEventTarget = noink ? this : this.target; - } } }); })(); \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple.html b/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple.html index 2fcd4d1..bea1ecca 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple.html +++ b/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple.html
@@ -113,10 +113,6 @@ transform: translate3d(0, 0, 0); } - :host([noink]) { - pointer-events: none; - } - #background, #waves, .wave-container,
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-slider/.bower.json index 45c26c09..77c5be8 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-slider/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-slider/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-slider", - "version": "1.0.7", + "version": "1.0.8", "description": "A material design-style slider", "license": "http://polymer.github.io/LICENSE.txt", "authors": "The Polymer Authors", @@ -10,13 +10,12 @@ "slider", "control" ], - "main": [ - "paper-slider.html" - ], + "main": "paper-slider.html", "repository": { "type": "git", "url": "git://github.com/PolymerElements/paper-slider.git" }, + "ignore": [], "dependencies": { "polymer": "Polymer/polymer#^1.0.0", "paper-input": "PolymerElements/paper-input#^1.0.0", @@ -33,15 +32,15 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, "homepage": "https://github.com/PolymerElements/paper-slider", - "_release": "1.0.7", + "_release": "1.0.8", "_resolution": { "type": "version", - "tag": "v1.0.7", - "commit": "087c9ecdfca14f4a3faf45006203de08a8910995" + "tag": "v1.0.8", + "commit": "5cad377a1321656a2bdc65644b1ad26ab76f1ecb" }, "_source": "git://github.com/PolymerElements/paper-slider.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-slider/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-slider/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/README.md b/third_party/polymer/v1_0/components-chromium/paper-slider/README.md index 15139a6..663dc1b 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-slider/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-slider/README.md
@@ -1,5 +1,23 @@ -paper-slider -============ + +<!--- + +This README is automatically generated from the comments in these files: +paper-slider.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-slider) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-slider)_ + + +##<paper-slider> + + +Material design: [Sliders](https://www.google.com/design/spec/components/sliders.html) `paper-slider` allows user to select a value from a range of values by moving the slider thumb. The interactive nature of the slider makes it a @@ -8,16 +26,15 @@ Example: -```html -<paper-slider></paper-slider> -``` + <paper-slider></paper-slider> -Use `min` and `max` to specify the slider range. Default is `0` to `100`. For example: -```html -<paper-slider min="10" max="200" value="110"></paper-slider> -``` +Use `min` and `max` to specify the slider range. Default is 0 to 100. -### Styling slider +Example: + + <paper-slider min="10" max="200" value="110"></paper-slider> + +### Styling The following custom properties and mixins are available for styling: @@ -32,20 +49,9 @@ `--paper-slider-font-color` | The pin's text color | `#fff` `--paper-slider-disabled-active-color` | The disabled progress bar color | `--google-grey-500` `--paper-slider-disabled-secondary-color` | The disabled secondary progress bar color | `--google-grey-300` +`--paper-slider-knob-start-color` | The fill color of the knob at the far left | `transparent` +`--paper-slider-knob-start-border-color` | The border color of the knob at the far left | `#c8c8c8` +`--paper-slider-pin-start-color` | The color of the pin at the far left | `#c8c8c8` `--paper-slider-height` | Height of the progress bar | `2px` -Example: -``` -paper-slider { - --paper-slider-bar-color: #fff; - --paper-slider-active-color: #0f9d58; - --paper-slider-knob-color: #0f9d58; - --paper-slider-pin-color: #0f9d58; - --paper-slider-font-color: #0f9d58; - --paper-slider-secondary-color: #0f9d58; - --paper-slider-disabled-active-color: #ccc; - --paper-slider-disabled-secondary-color: #ccc; - --paper-slider-height: 5px; -} -```
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/bower.json b/third_party/polymer/v1_0/components-chromium/paper-slider/bower.json index 16ed845..48c35ee0 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-slider/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-slider/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-slider", - "version": "1.0.7", + "version": "1.0.8", "description": "A material design-style slider", "license": "http://polymer.github.io/LICENSE.txt", "authors": "The Polymer Authors", @@ -10,13 +10,12 @@ "slider", "control" ], - "main": [ - "paper-slider.html" - ], + "main": "paper-slider.html", "repository": { "type": "git", "url": "git://github.com/PolymerElements/paper-slider.git" }, + "ignore": [], "dependencies": { "polymer": "Polymer/polymer#^1.0.0", "paper-input": "PolymerElements/paper-input#^1.0.0", @@ -33,7 +32,7 @@ "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" } }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js index eabb9bfb..51b615c 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js
@@ -282,12 +282,14 @@ }, _maxMarkersChanged: function(maxMarkers) { - var l = (this.max - this.min) / this.step; - if (!this.snaps && l > maxMarkers) { + if (!this.snaps) { this._setMarkers([]); - } else { - this._setMarkers(new Array(l)); } + var steps = Math.floor((this.max - this.min) / this.step); + if (steps > maxMarkers) { + steps = maxMarkers; + } + this._setMarkers(new Array(steps)); }, _mergeClasses: function(classes) {
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html index 20dab1b7..cf7bd89 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html +++ b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html
@@ -65,7 +65,9 @@ <template strip-whitespace=""> <style> :host { - display: inline-block; + @apply(--layout); + @apply(--layout-justified); + @apply(--layout-center); width: 200px; cursor: default; -webkit-user-select: none; @@ -86,8 +88,10 @@ #sliderContainer { position: relative; - width: calc(100% - 32px); - height: 32px; + width: 100%; + height: calc(30px + var(--paper-slider-height, 2px)); + margin-left: calc(15px + var(--paper-slider-height, 2px)/2); + margin-right: calc(15px + var(--paper-slider-height, 2px)/2); } #sliderContainer:focus { @@ -95,70 +99,67 @@ } #sliderContainer.editable { - float: left; - width: calc(100% - 72px); - margin: 12px 0; + margin-top: 12px; + margin-bottom: 12px; } .bar-container { position: absolute; top: 0; - left: 16px; - height: 100%; - width: 100%; + bottom: 0; + left: 0; + right: 0; overflow: hidden; } .ring > .bar-container { - left: 20px; - width: calc(100% - 4px); + left: calc(5px + var(--paper-slider-height, 2px)/2); transition: left 0.18s ease, width 0.18s ease; } - .ring.expand:not(.pin) > .bar-container { - left: 30px; - width: calc(100% - 14px); - } - .ring.expand.dragging > .bar-container { transition: none; } + .ring.expand:not(.pin) > .bar-container { + left: calc(15px + var(--paper-slider-height, 2px)/2); + } + #sliderBar { - position: absolute; - top: 15px; - left: 0; + padding: 15px 0; width: 100%; - padding: 8px 0; - margin: -8px 0; background-color: var(--paper-slider-bar-color, transparent); --paper-progress-height: var(--paper-slider-height, 2px); } .ring #sliderBar { - left: -4px; - width: calc(100% + 4px); + margin-left: calc(-5px - var(--paper-slider-height, 2px)/2); + width: calc(100% + 5px + var(--paper-slider-height, 2px)/2); } - .ring.expand:not(.pin) #sliderBar { - left: -14px; - width: calc(100% + 14px); + margin-left: calc(-15px - var(--paper-slider-height, 2px)/2); + width: calc(100% + 15px + var(--paper-slider-height, 2px)/2); } .slider-markers { position: absolute; - top: 15px; - left: 15px; - height: 2px; - width: calc(100% + 2px); + top: calc(14px + var(--paper-slider-height,2px)/2); + height: var(--paper-slider-height, 2px); + left: 0; + right: -1px; box-sizing: border-box; pointer-events: none; + @apply(--layout-horizontal); } + .slider-marker { + @apply(--layout-flex); + } .slider-markers::after, .slider-marker::after { content: ""; display: block; + margin-left: -1px; width: 2px; height: 2px; border-radius: 50%; @@ -166,15 +167,12 @@ } #sliderKnob { - @apply(--layout-center-justified); - @apply(--layout-center); - @apply(--layout-horizontal); - position: absolute; left: 0; top: 0; - width: 32px; - height: 32px; + margin-left: calc(-15px - var(--paper-slider-height, 2px)/2); + width: calc(30px + var(--paper-slider-height, 2px)); + height: calc(30px + var(--paper-slider-height, 2px)); } .transiting > #sliderKnob { @@ -195,20 +193,22 @@ } #sliderKnobInner { - width: 12px; - height: 12px; + margin: 10px; + width: calc(100% - 20px); + height: calc(100% - 20px); border-radius: 50%; background-color: var(--paper-slider-knob-color, --google-blue-700); -moz-box-sizing: border-box; box-sizing: border-box; - transition-property: height, width, background-color, border; + transition-property: margin, height, width, background-color, border; transition-duration: 0.1s; transition-timing-function: ease; } .expand:not(.pin) > #sliderKnob > #sliderKnobInner { + margin: 0; width: 100%; height: 100%; @@ -229,10 +229,10 @@ content: ""; position: absolute; top: 0; - left: 0; + left: 50%; + margin-left: -13px; width: 26px; height: 26px; - margin-left: 3px; border-radius: 50% 50% 50% 0; -webkit-transform: rotate(-45deg) scale(0) translate(0); @@ -258,7 +258,8 @@ content: attr(value); position: absolute; top: 0; - left: 0; + left: 50%; + margin-left: -16px; width: 32px; height: 26px; text-align: center; @@ -277,7 +278,6 @@ /* paper-input */ .slider-input { width: 50px; - float: right; overflow: hidden; --paper-input-container-input: { text-align: center; @@ -289,9 +289,14 @@ pointer-events: none; } + .disabled > #sliderKnob { + top: 2px; + margin-left: calc(-13px - var(--paper-slider-height, 2px)/2); + width: calc(26px + var(--paper-slider-height, 2px)); + height: calc(26px + var(--paper-slider-height, 2px)); + } + .disabled > #sliderKnob > #sliderKnobInner { - width: 8px; - height: 8px; background-color: var(--paper-slider-disabled-knob-color, --google-grey-500); } @@ -312,14 +317,14 @@ </div> <template is="dom-if" if="[[snaps]]"> - <div class="slider-markers horizontal layout"> + <div class="slider-markers"> <template is="dom-repeat" items="[[markers]]"> - <div class="slider-marker flex"></div> + <div class="slider-marker"></div> </template> </div> </template> - <div id="sliderKnob" class="center-justified center horizontal layout" on-down="_knobdown" on-up="_resetKnob" on-track="_onTrack" on-transitionend="_knobTransitionEnd"> + <div id="sliderKnob" on-down="_knobdown" on-up="_resetKnob" on-track="_onTrack" on-transitionend="_knobTransitionEnd"> <div id="sliderKnobInner" value$="[[immediateValue]]"></div> </div> </div>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-spinner/.travis.yml b/third_party/polymer/v1_0/components-chromium/paper-spinner/.travis.yml deleted file mode 100644 index f12cf79..0000000 --- a/third_party/polymer/v1_0/components-chromium/paper-spinner/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: dpHtK5BMl68o/D6cQO9VsQWBPVuTrFPC56NT6kBLbiQtmxG2E2FD8dN4cHuEWafZopwYSsLLmEIIK77FMaonTSmzos5EixIQyqGxWTyNTpthg0Jenzc+6vZEs3h+3LDodFjdZSu8FgKyxU8SFLLGjAsSy8aegUNBszy7/SY8FAM= - - secure: EASvFsWb/njjh3DOLD5Oz3nw4QPl4aIhDAIhU2qelb2UCp8Q/KGniU7VjNoQ7OSN05jh2ooz8Pu3cAhLmrWumJn2atXEXvRPKtT/+1Ciy3xFcvgmqM0RHB+7qSSOUwgvPW9bwdzVxxMjAW7Oqb7w3nVn9/mEv2sMPNSv7iEbiUI=
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-styles/.bower.json index 862c41b..4c605a5 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-styles/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-styles", - "version": "1.0.12", + "version": "1.0.13", "description": "Common (global) styles for Material Design elements.", "authors": [ "The Polymer Authors" @@ -29,11 +29,11 @@ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", "iron-component-page": "polymerelements/iron-component-page#^1.0.0" }, - "_release": "1.0.12", + "_release": "1.0.13", "_resolution": { "type": "version", - "tag": "v1.0.12", - "commit": "8ac5128a38249982982b3a1b3533d417d2dd7f18" + "tag": "v1.0.13", + "commit": "dd998025a0fc01bfe157dd72d5b91c7b5a70b909" }, "_source": "git://github.com/PolymerElements/paper-styles.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-styles/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/README.md b/third_party/polymer/v1_0/components-chromium/paper-styles/README.md index 82a7847..ef1c30c 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-styles/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/README.md
@@ -1,3 +1,38 @@ -# paper-styles -Material design CSS styles. +<!--- + +This README is automatically generated from the comments in these files: +paper-styles.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-styles) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-styles)_ + + +##<paper-styles> + + +The `<paper-styles>` component provides simple ways to use Material Design CSS styles +in your application. The following imports are available: + +1. [color.html](https://github.com/PolymerElements/paper-styles/blob/master/color.html): +a complete list of the colors defined in the Material Design [palette](https://www.google.com/design/spec/style/color.html) + +2. [default-theme.html](https://github.com/PolymerElements/paper-styles/blob/master/default-theme.html): text, +background and accent colors that match the default Material Design theme + +3. [shadow.html](https://github.com/PolymerElements/paper-styles/blob/master/shadow.html): Material Design +[elevation](https://www.google.com/design/spec/what-is-material/elevation-shadows.html) and shadow styles + +4. [typography.html](https://github.com/PolymerElements/paper-styles/blob/master/typography.html): +Material Design [font](http://www.google.com/design/spec/style/typography.html#typography-styles) styles and sizes + +5. [demo-pages.html](https://github.com/PolymerElements/paper-styles/blob/master/demo-pages.html): generic styles +used in the PolymerElements demo pages + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/bower.json b/third_party/polymer/v1_0/components-chromium/paper-styles/bower.json index c4398ee..a2dc4b6 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-styles/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-styles", - "version": "1.0.12", + "version": "1.0.13", "description": "Common (global) styles for Material Design elements.", "authors": [ "The Polymer Authors"
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html b/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html index c42067af5..fe55ec8 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html
@@ -284,7 +284,7 @@ html /deep/ .fixed-right { top: 0; right: 0; - botttom: 0; + bottom: 0; } html /deep/ .fixed-bottom { @@ -295,7 +295,7 @@ html /deep/ .fixed-left { top: 0; - botttom: 0; + bottom: 0; left: 0; }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/color.html b/third_party/polymer/v1_0/components-chromium/paper-styles/color.html index d907e68..5188790 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-styles/color.html +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/color.html
@@ -318,14 +318,14 @@ /* opacity for dark text on a light background */ --dark-divider-opacity: 0.12; - --dark-disabled-opacity: 0.26; /* or hint text */ - --dark-secondary-opacity: 0.54; /* or icon */ + --dark-disabled-opacity: 0.38; /* or hint text or icon */ + --dark-secondary-opacity: 0.54; --dark-primary-opacity: 0.87; /* opacity for light text on a dark background */ --light-divider-opacity: 0.12; - --light-disabled-opacity: 0.3; /* or hint text */ - --light-secondary-opacity: 0.7; /* or icon */ + --light-disabled-opacity: 0.3; /* or hint text or icon */ + --light-secondary-opacity: 0.7; --light-primary-opacity: 1.0; }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/index.html b/third_party/polymer/v1_0/components-chromium/paper-styles/index.html index caf55c5..8e96ebe0 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-styles/index.html +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/index.html
@@ -2,11 +2,11 @@ <!-- @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 +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 +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <html> <head>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/paper-styles.html b/third_party/polymer/v1_0/components-chromium/paper-styles/paper-styles.html index 7bee9dd..9eca03a7 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-styles/paper-styles.html +++ b/third_party/polymer/v1_0/components-chromium/paper-styles/paper-styles.html
@@ -30,7 +30,10 @@ 5. [demo-pages.html](https://github.com/PolymerElements/paper-styles/blob/master/demo-pages.html): generic styles used in the PolymerElements demo pages -@group Iron Elements +We recommend importing each of these individual files, and using the style mixins +available in each ones, rather than the aggregated `paper-styles.html` as a whole. + +@group Paper Elements @pseudoElement paper-styles @demo demo/index.html -->
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-tabs/.bower.json index d409a31..dfc1783d 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-tabs/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-tabs/.bower.json
@@ -1,6 +1,6 @@ { "name": "paper-tabs", - "version": "1.0.10", + "version": "1.1.0", "license": "http://polymer.github.io/LICENSE.txt", "description": "Material design tabs", "private": true, @@ -36,15 +36,16 @@ "paper-toolbar": "polymerelements/paper-toolbar#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "iron-pages": "PolymerElements/iron-pages#^1.0.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/paper-tabs", - "_release": "1.0.10", + "_release": "1.1.0", "_resolution": { "type": "version", - "tag": "v1.0.10", - "commit": "d9f518810b7313f3e5a29383d3bb86de0b260319" + "tag": "v1.1.0", + "commit": "e30132d4bd150720b657ab194af59f43613d13d5" }, "_source": "git://github.com/PolymerElements/paper-tabs.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/.travis.yml b/third_party/polymer/v1_0/components-chromium/paper-tabs/.travis.yml deleted file mode 100644 index 27e770d..0000000 --- a/third_party/polymer/v1_0/components-chromium/paper-tabs/.travis.yml +++ /dev/null
@@ -1,28 +0,0 @@ -language: node_js -sudo: false -matrix: - include: - - node_js: stable - script: xvfb-run wct - addons: - firefox: latest - apt: - sources: - - google-chrome - packages: - - google-chrome-stable - - node_js: node - script: - - | - if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then - wct -s 'default' - fi -before_script: -- npm install web-component-tester -- npm install bower -- export PATH=$PWD/node_modules/.bin:$PATH -- bower install -env: - global: - - secure: ieKt2HWOdClqU7OyYA20DFlWduaM0IDk91lO7mWySQL6r55SSB4DnUCgVycQJf0L6S8vyY/fbC/vFP0notyz3MvMAz1NwpRzAI9mKkVWJuaBbm9Ql9PewjanX42chbz3XyqZofXVkfBywmj61NyPM7VRVwhEHmOeYgyFUyV9cls= - - secure: g7yrxdFIVMIjkYBKZ29FHUX3noS6u1lvjUmaAaG28rGaEfXK4XR9fhZABR+6ydAjLjdo+WUMvTp4oi6HYrb6ToByprEli/fTexjeGuagDc5r5R84u3CusBuw9YYHDjstHCBFmIZndD+r4PRXkWvYatciF9c0NCHoVrjTH/woe9g=
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/bower.json b/third_party/polymer/v1_0/components-chromium/paper-tabs/bower.json index 0bff065..c68ad8f 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-tabs/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-tabs/bower.json
@@ -1,6 +1,6 @@ { "name": "paper-tabs", - "version": "1.0.10", + "version": "1.1.0", "license": "http://polymer.github.io/LICENSE.txt", "description": "Material design tabs", "private": true, @@ -36,7 +36,8 @@ "paper-toolbar": "polymerelements/paper-toolbar#^1.0.0", "test-fixture": "polymerelements/test-fixture#^1.0.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0", - "web-component-tester": "*", + "web-component-tester": "polymer/web-component-tester#^3.4.0", "iron-pages": "PolymerElements/iron-pages#^1.0.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html index 0d65a86..7d18acd 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html +++ b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html
@@ -7,7 +7,6 @@ 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-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <link rel="import" href="../iron-behaviors/iron-control-state.html"> <link rel="import" href="../iron-behaviors/iron-button-state.html"> @@ -69,7 +68,9 @@ -webkit-transform: translateZ(0); transform: translateZ(0); transition: opacity 0.1s cubic-bezier(0.4, 0.0, 1, 1); - + @apply(--layout-horizontal); + @apply(--layout-center-center); + @apply(--layout-flex-auto); @apply(--paper-tab-content); } @@ -102,7 +103,7 @@ <template> - <div class="tab-content flex-auto center-center horizontal layout"> + <div class="tab-content"> <content></content> </div>
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs-extracted.js index 5ef4d19..5ce67b68 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs-extracted.js
@@ -150,7 +150,7 @@ }, _computeTabsContentClass: function(scrollable) { - return scrollable ? 'scrollable' : 'horizontal layout'; + return scrollable ? 'scrollable' : 'horizontal'; }, _computeSelectionBarClass: function(noBar, alignBottom) {
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html index 9e8dcfc..65533ed 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html +++ b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html
@@ -8,7 +8,6 @@ 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-flex-layout/iron-flex-layout.html"> -<link rel="import" href="../iron-flex-layout/classes/iron-flex-layout.html"> <link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html"> <link rel="import" href="../iron-menu-behavior/iron-menubar-behavior.html"> <link rel="import" href="../iron-icon/iron-icon.html"> @@ -56,16 +55,23 @@ element in `paper-tab`. Example: + <style is="custom-style"> + .link { + @apply(--layout-horizontal); + @apply(--layout-center-center); + } + } + </style> <paper-tabs selected="0"> <paper-tab link> - <a href="#link1" class="horizontal center-center layout">TAB ONE</a> + <a href="#link1" class="link">TAB ONE</a> </paper-tab> <paper-tab link> - <a href="#link2" class="horizontal center-center layout">TAB TWO</a> + <a href="#link2" class="link">TAB TWO</a> </paper-tab> <paper-tab link> - <a href="#link3" class="horizontal center-center layout">TAB THREE</a> + <a href="#link3" class="link">TAB THREE</a> </paper-tab> </paper-tabs> @@ -112,6 +118,7 @@ height: 100%; white-space: nowrap; overflow: hidden; + @apply(--layout-flex); } #tabsContent { @@ -123,6 +130,10 @@ white-space: nowrap; } + #tabsContent.horizontal { + @apply(--layout-horizontal); + } + .hidden { display: none; } @@ -181,7 +192,7 @@ <paper-icon-button icon="paper-tabs:chevron-left" class$="[[_computeScrollButtonClass(_leftHidden, scrollable, hideScrollButtons)]]" on-up="_onScrollButtonUp" on-down="_onLeftScrollButtonDown" tabindex="-1"></paper-icon-button> - <div id="tabsContainer" class="flex" on-track="_scroll" on-down="_down"> + <div id="tabsContainer" on-track="_scroll" on-down="_down"> <div id="tabsContent" class$="[[_computeTabsContentClass(scrollable)]]">
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/.bower.json b/third_party/polymer/v1_0/components-chromium/paper-toolbar/.bower.json index dcfc7cb0..8981936 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-toolbar/.bower.json
@@ -1,12 +1,10 @@ { "name": "paper-toolbar", - "version": "1.0.4", + "version": "1.1.1", "license": "http://polymer.github.io/LICENSE.txt", "description": "A material design toolbar that is easily customizable", "private": true, - "main": [ - "paper-toolbar.html" - ], + "main": "paper-toolbar.html", "authors": [ "The Polymer Authors" ], @@ -22,22 +20,24 @@ }, "dependencies": { "paper-styles": "PolymerElements/paper-styles#^1.0.0", - "polymer": "Polymer/polymer#^1.0.0" + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "polymer": "Polymer/polymer#^1.2.0" }, "devDependencies": { + "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-icons": "PolymerElements/iron-icons#^1.0.0", "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", - "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "web-component-tester": "*", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, + "ignore": [], "homepage": "https://github.com/PolymerElements/paper-toolbar", - "_release": "1.0.4", + "_release": "1.1.1", "_resolution": { "type": "version", - "tag": "v1.0.4", - "commit": "15096d1c9ee6cc547eaf078b431f3e07d0968367" + "tag": "v1.1.1", + "commit": "b82f2fcb0737315627880073a2d50eb084bdd529" }, "_source": "git://github.com/PolymerElements/paper-toolbar.git", "_target": "^1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/CONTRIBUTING.md b/third_party/polymer/v1_0/components-chromium/paper-toolbar/CONTRIBUTING.md new file mode 100644 index 0000000..7b101415 --- /dev/null +++ b/third_party/polymer/v1_0/components-chromium/paper-toolbar/CONTRIBUTING.md
@@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that!
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/README.md b/third_party/polymer/v1_0/components-chromium/paper-toolbar/README.md index 997c345c..2f6d370 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/README.md +++ b/third_party/polymer/v1_0/components-chromium/paper-toolbar/README.md
@@ -1,5 +1,23 @@ -paper-toolbar -============ + +<!--- + +This README is automatically generated from the comments in these files: +paper-toolbar.html + +Edit those files, and our readme bot will duplicate them over here! +Edit this file, and the bot will squash your changes :) + +--> + +[](https://travis-ci.org/PolymerElements/paper-toolbar) + +_[Demo and API Docs](https://elements.polymer-project.org/elements/paper-toolbar)_ + + +##<paper-toolbar> + + +Material design: [Toolbars](https://www.google.com/design/spec/components/toolbars.html) `paper-toolbar` is a horizontal bar containing items that can be used for label, navigation, search and actions. The items place inside the @@ -9,42 +27,34 @@ Example: -```html -<paper-toolbar> - <paper-icon-button icon="menu" on-tap="{{menuAction}}"></paper-icon-button> - <div class="title">Title</div> - <paper-icon-button icon="more" on-tap="{{moreAction}}"></paper-icon-button> -</paper-toolbar> -``` + <paper-toolbar> + <paper-icon-button icon="menu" on-tap="menuAction"></paper-icon-button> + <div class="title">Title</div> + <paper-icon-button icon="more-vert" on-tap="moreAction"></paper-icon-button> + </paper-toolbar> `paper-toolbar` has a standard height, but can made be taller by setting `tall` class on the `paper-toolbar`. This will make the toolbar 3x the normal height. -```html -<paper-toolbar class="tall"> - <paper-icon-button icon="menu"></paper-icon-button> -</paper-toolbar> -``` + <paper-toolbar class="tall"> + <paper-icon-button icon="menu"></paper-icon-button> + </paper-toolbar> Apply `medium-tall` class to make the toolbar medium tall. This will make the toolbar 2x the normal height. -```html -<paper-toolbar class="medium-tall"> - <paper-icon-button icon="menu"></paper-icon-button> -</paper-toolbar> -``` + <paper-toolbar class="medium-tall"> + <paper-icon-button icon="menu"></paper-icon-button> + </paper-toolbar> When `tall`, items can pin to either the top (default), middle or bottom. Use `middle` class for middle content and `bottom` class for bottom content. -```html -<paper-toolbar class="tall"> - <paper-icon-button icon="menu"></paper-icon-button> - <div class="title middle">Middle Title</div> - <div class="title bottom">Bottom Title</div> -</paper-toolbar> -``` + <paper-toolbar class="tall"> + <paper-icon-button icon="menu"></paper-icon-button> + <div class="middle title">Middle Title</div> + <div class="bottom title">Bottom Title</div> + </paper-toolbar> For `medium-tall` toolbar, the middle and bottom contents overlap and are pinned to the bottom. But `middleJustify` and `bottomJustify` attributes are @@ -53,8 +63,27 @@ To make an element completely fit at the bottom of the toolbar, use `fit` along with `bottom`. -```html -<paper-toolbar class="tall"> - <div id="progressBar" class="bottom fit"></div> -</paper-toolbar> -``` \ No newline at end of file + <paper-toolbar class="tall"> + <div id="progressBar" class="bottom fit"></div> + </paper-toolbar> + +### Styling + +The following custom properties and mixins are available for styling: + +Custom property | Description | Default +----------------|-------------|---------- +`--paper-toolbar-background` | Toolbar background color | `--default-primary-color` +`--paper-toolbar-color` | Toolbar foreground color | `--text-primary-color` +`--paper-toolbar-height` | Custom height for toolbar | `64px` +`--paper-toolbar-sm-height` | Custom height for small screen toolbar | `56px` +`--paper-toolbar` | Mixin applied to the toolbar | `{}` +`--paper-toolbar-medium` | Mixin applied to medium height toolbar | `{}` +`--paper-toolbar-tall` | Mixin applied to tall height toolbar | `{}` + +### Accessibility + +`<paper-toolbar>` has `role="toolbar"` by default. Any elements with the class `title` will +be used as the label of the toolbar via `aria-labelledby`. + +
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/bower.json b/third_party/polymer/v1_0/components-chromium/paper-toolbar/bower.json index fee8df50..b1d70f91 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/bower.json +++ b/third_party/polymer/v1_0/components-chromium/paper-toolbar/bower.json
@@ -1,12 +1,10 @@ { "name": "paper-toolbar", - "version": "1.0.4", + "version": "1.1.1", "license": "http://polymer.github.io/LICENSE.txt", "description": "A material design toolbar that is easily customizable", "private": true, - "main": [ - "paper-toolbar.html" - ], + "main": "paper-toolbar.html", "authors": [ "The Polymer Authors" ], @@ -22,14 +20,16 @@ }, "dependencies": { "paper-styles": "PolymerElements/paper-styles#^1.0.0", - "polymer": "Polymer/polymer#^1.0.0" + "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0", + "polymer": "Polymer/polymer#^1.2.0" }, "devDependencies": { + "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "iron-icons": "PolymerElements/iron-icons#^1.0.0", "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", - "iron-component-page": "PolymerElements/iron-component-page#^1.0.0", "test-fixture": "PolymerElements/test-fixture#^1.0.0", "web-component-tester": "*", "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" - } + }, + "ignore": [] }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js index 8e8f23b..1aef616 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js
@@ -1,20 +1,4 @@ -(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({ - +Polymer({ is: 'paper-toolbar', hostAttributes: { @@ -22,7 +6,6 @@ }, properties: { - /** * Controls how the items are aligned horizontally when they are placed * at the bottom. @@ -110,27 +93,9 @@ } }, - _computeBarClassName: function(barJustify) { - var classObj = { - 'center': true, - 'horizontal': true, - 'layout': true, - 'toolbar-tools': true - }; + _computeBarExtraClasses: function(barJustify) { + if (!barJustify) return ''; - // If a blank string or any falsy value is given, no other class name is - // added. - if (barJustify) { - var justifyClassName = (barJustify === 'justified') ? - barJustify : - barJustify + '-justified'; - - classObj[justifyClassName] = true; - } - - return classNames(classObj); + return barJustify + (barJustify === 'justified' ? '' : '-justified'); } - - }); - - }()); \ No newline at end of file + }); \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html b/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html index 7acb0c9..11838111 100644 --- a/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html +++ b/third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar.html
@@ -6,9 +6,13 @@ 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"> +<link rel="import" href="../paper-styles/default-theme.html"> +<link rel="import" href="../paper-styles/typography.html"> +<link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <!-- +Material design: [Toolbars](https://www.google.com/design/spec/components/toolbars.html) + `paper-toolbar` is a horizontal bar containing items that can be used for label, navigation, search and actions. The items place inside the `paper-toolbar` are projected into a `class="horizontal center layout"` container inside of @@ -17,34 +21,42 @@ Example: - <paper-toolbar> - <paper-icon-button icon="menu" on-tap="menuAction"></paper-icon-button> - <div class="title">Title</div> - <paper-icon-button icon="more-vert" on-tap="moreAction"></paper-icon-button> - </paper-toolbar> +```html +<paper-toolbar> + <paper-icon-button icon="menu" on-tap="menuAction"></paper-icon-button> + <div class="title">Title</div> + <paper-icon-button icon="more-vert" on-tap="moreAction"></paper-icon-button> +</paper-toolbar> +``` `paper-toolbar` has a standard height, but can made be taller by setting `tall` class on the `paper-toolbar`. This will make the toolbar 3x the normal height. - <paper-toolbar class="tall"> - <paper-icon-button icon="menu"></paper-icon-button> - </paper-toolbar> +```html +<paper-toolbar class="tall"> + <paper-icon-button icon="menu"></paper-icon-button> +</paper-toolbar> +``` Apply `medium-tall` class to make the toolbar medium tall. This will make the toolbar 2x the normal height. - <paper-toolbar class="medium-tall"> - <paper-icon-button icon="menu"></paper-icon-button> - </paper-toolbar> +```html +<paper-toolbar class="medium-tall"> + <paper-icon-button icon="menu"></paper-icon-button> +</paper-toolbar> +``` When `tall`, items can pin to either the top (default), middle or bottom. Use `middle` class for middle content and `bottom` class for bottom content. - <paper-toolbar class="tall"> - <paper-icon-button icon="menu"></paper-icon-button> - <div class="middle title">Middle Title</div> - <div class="bottom title">Bottom Title</div> - </paper-toolbar> +```html +<paper-toolbar class="tall"> + <paper-icon-button icon="menu"></paper-icon-button> + <div class="middle title">Middle Title</div> + <div class="bottom title">Bottom Title</div> +</paper-toolbar> +``` For `medium-tall` toolbar, the middle and bottom contents overlap and are pinned to the bottom. But `middleJustify` and `bottomJustify` attributes are @@ -53,9 +65,11 @@ To make an element completely fit at the bottom of the toolbar, use `fit` along with `bottom`. - <paper-toolbar class="tall"> - <div id="progressBar" class="bottom fit"></div> - </paper-toolbar> +```html +<paper-toolbar class="tall"> + <div id="progressBar" class="bottom fit"></div> +</paper-toolbar> +``` ### Styling @@ -63,9 +77,14 @@ Custom property | Description | Default ----------------|-------------|---------- +`--paper-toolbar-title` | Mixin applied to the title of the toolbar | `{}` `--paper-toolbar-background` | Toolbar background color | `--default-primary-color` `--paper-toolbar-color` | Toolbar foreground color | `--text-primary-color` +`--paper-toolbar-height` | Custom height for toolbar | `64px` +`--paper-toolbar-sm-height` | Custom height for small screen toolbar | `56px` `--paper-toolbar` | Mixin applied to the toolbar | `{}` +`--paper-toolbar-medium` | Mixin applied to medium height toolbar | `{}` +`--paper-toolbar-tall` | Mixin applied to tall height toolbar | `{}` ### Accessibility @@ -76,170 +95,188 @@ --> </head><body><dom-module id="paper-toolbar"> - - <style> - :host { - /* technical */ - display: block; - position: relative; - box-sizing: border-box; - -moz-box-sizing: border-box; - - /* size */ - height: 64px; - - background: var(--paper-toolbar-background, --default-primary-color); - color: var(--paper-toolbar-color, --text-primary-color); - - @apply(--paper-toolbar); - } - - :host(.animate) { - /* transition */ - transition: height 0.18s ease-in; - } - - :host(.medium-tall) { - height: 128px; - } - - :host(.tall) { - height: 192px; - } - - .toolbar-tools { - position: relative; - height: 64px; - padding: 0 16px; - pointer-events: none; - } - - /* - * TODO: Where should media query breakpoints live so they can be shared between elements? - */ - - @media (max-width: 639px) { + <template> + <style> :host { - height: 56px; + /* technical */ + display: block; + position: relative; + box-sizing: border-box; + -moz-box-sizing: border-box; + + /* size */ + height: var(--paper-toolbar-height, 64px); + + background: var(--paper-toolbar-background, --default-primary-color); + color: var(--paper-toolbar-color, --text-primary-color); + + @apply(--paper-toolbar); + } + + :host(.animate) { + /* transition */ + transition: height 0.18s ease-in; } :host(.medium-tall) { - height: 112px; + height: calc(var(--paper-toolbar-height, 64px) * 2); + @apply(--paper-toolbar-medium); } :host(.tall) { - height: 168px; + height: calc(var(--paper-toolbar-height, 64px) * 3); + @apply(--paper-toolbar-tall); } .toolbar-tools { - height: 56px; + position: relative; + height: var(--paper-toolbar-height, 64px); + padding: 0 16px; + pointer-events: none; + @apply(--layout-horizontal); + @apply(--layout-center); } - } - - #topBar { - position: relative; - } - - /* middle bar */ - #middleBar { - position: absolute; - top: 0; - right: 0; - left: 0; - } - - :host(.tall) #middleBar, - :host(.medium-tall) #middleBar { - -webkit-transform: translateY(100%); - transform: translateY(100%); - } - - /* bottom bar */ - #bottomBar { - position: absolute; - right: 0; - bottom: 0; - left: 0; - } - - /* - * make elements (e.g. buttons) respond to mouse/touch events - * - * `.toolbar-tools` disables touch events so multiple toolbars can stack and not - * absorb events. All children must have pointer events re-enabled to work as - * expected. - */ - .toolbar-tools > ::content > *:not([disabled]) { - pointer-events: auto; - } - - .toolbar-tools > ::content .title { - @apply(--paper-font-title); - @apply(--layout-flex); - - pointer-events: none; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; /* - * Polymer/polymer/issues/1525 - * --paper-font-title defines a `font-weight` - * let's override its value, but we need `important!` - * because all mixins are resolved in rule's selector that has higher precedence - * than the current selector. + * TODO: Where should media query breakpoints live so they can be shared between elements? */ - font-weight: 400 !important; - } - /** - * TODO: Refactor these selectors - * Work in progress. - */ - .toolbar-tools > ::content paper-icon-button[icon=menu] { - margin-right: 24px; - } + @media (max-width: 639px) { + :host { + height: var(--paper-toolbar-sm-height, 56px); + } - .toolbar-tools > ::content > .title, - .toolbar-tools > ::content[select=".middle"] > .title, - .toolbar-tools > ::content[select=".bottom"] > .title { - margin-left: 56px; - } + :host(.medium-tall) { + height: calc(var(--paper-toolbar-sm-height, 56px) * 2); + } - .toolbar-tools > ::content > paper-icon-button + .title, - .toolbar-tools > ::content[select=".middle"] paper-icon-button + .title, - .toolbar-tools > ::content[select=".bottom"] paper-icon-button + .title { - margin-left: 0; - } + :host(.tall) { + height: calc(var(--paper-toolbar-sm-height, 56px) * 3); + } - .toolbar-tools > ::content > .fit { - position: absolute; - top: auto; - right: 0; - bottom: 0; - left: 0; - width: auto; - margin: 0; - } + .toolbar-tools { + height: var(--paper-toolbar-sm-height, 56px); + } + } - </style> + #topBar { + position: relative; + } - <template> + /* middle bar */ + #middleBar { + position: absolute; + top: 0; + right: 0; + left: 0; + } - <div id="topBar" class$="[[_computeBarClassName(justify)]]"> + :host(.tall) #middleBar, + :host(.medium-tall) #middleBar { + -webkit-transform: translateY(100%); + transform: translateY(100%); + } + + /* bottom bar */ + #bottomBar { + position: absolute; + right: 0; + bottom: 0; + left: 0; + } + + /* + * make elements (e.g. buttons) respond to mouse/touch events + * + * `.toolbar-tools` disables touch events so multiple toolbars can stack and not + * absorb events. All children must have pointer events re-enabled to work as + * expected. + */ + .toolbar-tools > ::content > *:not([disabled]) { + pointer-events: auto; + } + + .toolbar-tools > ::content .title { + @apply(--paper-font-common-base); + + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: 20px; + font-weight: 400; + line-height: 1; + pointer-events: none; + + @apply(--layout-flex); + @apply(--paper-toolbar-title); + } + + /** + * TODO: Refactor these selectors + * Work in progress. + */ + .toolbar-tools > ::content paper-icon-button[icon=menu] { + margin-right: 24px; + } + + .toolbar-tools > ::content > .title, + .toolbar-tools > ::content[select=".middle"] > .title, + .toolbar-tools > ::content[select=".bottom"] > .title { + margin-left: 56px; + } + + .toolbar-tools > ::content > paper-icon-button + .title, + .toolbar-tools > ::content[select=".middle"] paper-icon-button + .title, + .toolbar-tools > ::content[select=".bottom"] paper-icon-button + .title { + margin-left: 0; + } + + .toolbar-tools > ::content > .fit { + position: absolute; + top: auto; + right: 0; + bottom: 0; + left: 0; + width: auto; + margin: 0; + } + + /* TODO(noms): Until we have a better solution for classes that don't use + * /deep/ create our own. + */ + .start-justified { + @apply(--layout-start-justified); + } + + .center-justified { + @apply(--layout-center-justified); + } + + .end-justified { + @apply(--layout-end-justified); + } + + .around-justified { + @apply(--layout-around-justified); + } + + .justified { + @apply(--layout-justified); + } + </style> + + <div id="topBar" class$="toolbar-tools [[_computeBarExtraClasses(justify)]]"> <content select=":not(.middle):not(.bottom)"></content> </div> - <div id="middleBar" class$="[[_computeBarClassName(middleJustify)]]"> + <div id="middleBar" class$="toolbar-tools [[_computeBarExtraClasses(middleJustify)]]"> <content select=".middle"></content> </div> - <div id="bottomBar" class$="[[_computeBarClassName(bottomJustify)]]"> + <div id="bottomBar" class$="toolbar-tools [[_computeBarExtraClasses(bottomJustify)]]"> <content select=".bottom"></content> </div> - </template> -</dom-module> - + </dom-module> <script src="paper-toolbar-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/.bower.json b/third_party/polymer/v1_0/components-chromium/polymer/.bower.json index abf79d8..21f137c 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/.bower.json +++ b/third_party/polymer/v1_0/components-chromium/polymer/.bower.json
@@ -1,6 +1,6 @@ { "name": "polymer", - "version": "1.2.1", + "version": "1.2.3", "main": [ "polymer.html" ], @@ -18,18 +18,18 @@ "url": "https://github.com/Polymer/polymer.git" }, "dependencies": { - "webcomponentsjs": "^0.7.2" + "webcomponentsjs": "^0.7.18" }, "devDependencies": { "web-component-tester": "*" }, "private": true, "homepage": "https://github.com/Polymer/polymer", - "_release": "1.2.1", + "_release": "1.2.3", "_resolution": { "type": "version", - "tag": "v1.2.1", - "commit": "be2d57a329244735ca7aac34ac56c96b6270ae79" + "tag": "v1.2.3", + "commit": "aa535d1675342007cbf64dc9c66497cf74cbc616" }, "_source": "git://github.com/Polymer/polymer.git", "_target": "^v1.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/bower.json b/third_party/polymer/v1_0/components-chromium/polymer/bower.json index bc97dc4..8f88ea2 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/bower.json +++ b/third_party/polymer/v1_0/components-chromium/polymer/bower.json
@@ -1,6 +1,6 @@ { "name": "polymer", - "version": "1.2.1", + "version": "1.2.3", "main": [ "polymer.html" ], @@ -18,7 +18,7 @@ "url": "https://github.com/Polymer/polymer.git" }, "dependencies": { - "webcomponentsjs": "^0.7.2" + "webcomponentsjs": "^0.7.18" }, "devDependencies": { "web-component-tester": "*"
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/build.log b/third_party/polymer/v1_0/components-chromium/polymer/build.log index a625291..9685b44a 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/build.log +++ b/third_party/polymer/v1_0/components-chromium/polymer/build.log
@@ -1,27 +1,433 @@ BUILD LOG --------- -Build Time: 2015-10-29T15:32:35-0700 +Build Time: 2015-11-16T17:06:23-0800 NODEJS INFORMATION ================== -nodejs: v4.2.1 -gulp: 3.9.0 -gulp-audit: 1.0.0 -gulp-rename: 1.2.2 -gulp-vulcanize: 6.0.1 -lazypipe: 0.2.4 -polyclean: 1.2.0 -web-component-tester: 3.3.29 -run-sequence: 1.1.4 +nodejs: v5.0.0 +binaryextensions: 1.0.0 +clone-stats: 0.0.1 +core-util-is: 1.0.1 +duplexer: 0.1.1 +escape-regexp-component: 1.0.2 +global: 2.0.1 +globule: 0.1.0 +is-utf8: 0.2.0 +keep-alive-agent: 0.0.1 +lazystream: 0.1.0 +match-stream: 0.0.2 +object-component: 0.0.3 +parseqs: 0.0.2 +parseuri: 0.0.2 +parsejson: 0.0.1 +sequencify: 0.0.7 +to-array: 0.1.3 +util-extend: 1.0.1 +xmlhttprequest: 1.5.0 +adm-zip: 0.4.7 +abbrev: 1.0.7 +ansi-cyan: 0.1.1 +ansi-red: 0.1.1 +ansi-styles: 2.1.0 +ansi-regex: 2.0.0 +after: 0.8.1 +amdefine: 1.0.0 +ansi-wrap: 0.1.0 +arr-union: 2.1.0 +arr-diff: 1.1.0 +arr-flatten: 1.0.1 +array-differ: 1.0.0 +archiver: 0.14.4 +archy: 1.0.0 +accepts: 1.2.13 +array-slice: 0.2.3 +array-union: 1.0.1 +array-uniq: 1.0.2 +asap: 2.0.3 +array-flatten: 1.1.1 +arraybuffer.slice: 0.0.6 +balanced-match: 0.2.1 +asn1: 0.1.11 +assert-plus: 0.1.5 +async: 1.5.0 +aws-sign2: 0.5.0 +backo2: 1.0.2 +beeper: 1.1.0 +base64-arraybuffer: 0.1.2 +base64-js: 0.0.6 +better-assert: 1.0.2 +benchmark: 1.0.0 +backoff: 2.4.1 +bindings: 1.2.1 +binary: 0.3.0 +base64id: 0.1.0 +blob: 0.0.4 +boom: 0.4.2 +bl: 0.9.4 +brace-expansion: 1.1.1 +buffers: 0.1.1 +bufferutil: 1.2.1 +bluebird: 2.10.2 +browserstack: 1.2.0 +callsite: 1.0.0 +buffer-crc32: 0.2.5 +camelcase-keys: 1.0.0 +camelcase: 1.2.1 +clone: 1.0.2 +chalk: 1.1.1 +cleankill: 1.0.2 +caseless: 0.8.0 +commander: 2.6.0 +builtin-modules: 1.1.0 +compress-commons: 0.2.9 +chainsaw: 0.1.0 +component-emitter: 1.1.2 +combined-stream: 0.0.7 +component-bind: 1.0.0 +cookie: 0.1.3 +component-inherit: 0.0.3 +concat-map: 0.0.1 +configstore: 1.3.0 +content-type: 1.0.1 +cookie-signature: 1.0.6 +content-disposition: 0.5.0 +crc32-stream: 0.3.4 +crc: 3.2.1 +cryptiles: 0.2.2 +csv-parse: 1.0.0 +csv: 0.4.6 +csv-generate: 0.0.6 +csv-stringify: 0.0.8 +deep-extend: 0.4.0 +decamelize: 1.1.1 +debuglog: 1.0.1 +ctype: 0.5.3 +deprecated: 0.0.1 del: 1.2.1 +deep-is: 0.1.3 +defaults: 1.0.3 +doctrine: 0.7.0 +dezalgo: 1.0.3 +dom5: 1.2.0 +delayed-stream: 0.0.5 +duplexer2: 0.0.2 +depd: 1.0.1 +destroy: 1.0.3 +each-async: 1.1.1 +dtrace-provider: 0.6.0 +duplexify: 3.4.2 +end-of-stream: 0.1.5 +ee-first: 1.1.1 +debug: 2.2.0 +escape-string-regexp: 1.0.3 +engine.io-client: 1.5.4 +engine.io: 1.5.4 +es6-promise: 2.3.0 +error-ex: 1.3.0 +estraverse: 3.1.0 +esutils: 1.1.6 +extend-shallow: 1.1.4 +escape-html: 1.0.2 +etag: 1.7.0 +extend: 2.0.1 +engine.io-parser: 1.2.2 +fancy-log: 1.1.0 +fast-levenshtein: 1.0.7 +find-index: 0.1.1 +extsprintf: 1.2.0 +express: 4.13.3 +finalhandler: 0.4.0 +first-chunk-stream: 1.0.0 +find-up: 1.0.0 +findup-sync: 0.3.0 +forever-agent: 0.5.2 +flagged-respawn: 0.3.1 +form-data: 0.2.0 +formidable: 1.0.17 +gaze: 0.5.2 +forwarded: 0.1.0 +github-url-from-git: 1.4.0 +fresh: 0.3.0 +get-stdin: 5.0.0 +github-url-from-username-repo: 1.0.2 +fstream: 0.1.31 +glob: 5.0.15 +glob-stream: 3.1.18 +glob-watcher: 0.0.6 +glob2base: 0.0.12 +globby: 2.1.0 +generate-function: 2.0.0 +generate-object-property: 1.2.0 +graceful-fs: 4.1.2 +graceful-readlink: 1.0.1 +gulp-audit: 1.0.0 +glogg: 1.0.0 gulp-replace: 0.5.4 +got: 3.3.1 +gulp-rename: 1.2.2 +freeport: 1.0.5 +gulp-vulcanize: 6.0.1 +gulplog: 1.0.0 +gulp-util: 3.0.7 +has-ansi: 2.0.0 +has-binary: 0.1.6 +has-gulplog: 0.1.0 +has-color: 0.1.7 +has-cors: 1.0.3 +hosted-git-info: 2.1.4 +has-binary-data: 0.1.3 +hawk: 1.1.1 +hydrolysis: 1.19.3 +inflight: 1.0.4 +hoek: 0.9.1 +inherits: 2.0.1 +infinity-agent: 2.0.3 +http-errors: 1.3.1 +http-signature: 0.11.0 +ini: 1.3.4 +indent-string: 2.1.0 +ipaddr.js: 1.0.1 +interpret: 0.6.6 +indexof: 0.0.1 +is-arrayish: 0.2.1 +is-my-json-valid: 2.12.3 +is-builtin-module: 1.0.0 +is-absolute: 0.1.7 +is-path-cwd: 1.0.0 +is-path-in-cwd: 1.0.0 +is-npm: 1.0.0 +is-property: 1.0.2 +is-path-inside: 1.0.0 +is-finite: 1.0.1 +istextorbinary: 1.0.2 +is-redirect: 1.0.0 +isarray: 0.0.1 +isstream: 0.1.2 +json-parse-helpfulerror: 1.0.3 +is-relative: 0.1.3 +jju: 1.2.1 +is-stream: 1.0.1 +json-stringify-safe: 5.0.1 +json3: 3.2.6 +kind-of: 1.1.0 +lazypipe: 0.2.4 +lodash._basecopy: 3.0.1 +jsonpointer: 2.0.0 +lodash: 1.0.2 +lodash._basevalues: 3.0.0 +lodash._basetostring: 3.0.1 +levn: 0.2.5 +launchpad: 0.4.9 +lodash._isiterateecall: 3.0.9 +lodash._getnative: 3.9.1 +lodash._reescape: 3.0.0 +lodash._reevaluate: 3.0.0 +lodash.isarguments: 3.0.4 +lodash.escape: 3.0.0 +lodash._reinterpolate: 3.0.0 +liftoff: 2.2.0 +lodash.isarray: 3.0.4 +load-json-file: 1.0.1 +lodash.restparam: 3.6.1 +lodash.keys: 3.1.2 +lodash-node: 2.4.1 +lodash.template: 3.6.2 +loud-rejection: 1.0.0 +lodash.templatesettings: 3.1.0 +lowercase-keys: 1.0.0 +media-typer: 0.3.0 +meow: 3.5.0 +map-obj: 1.0.1 +mime-db: 1.19.0 +methods: 1.1.1 +merge-descriptors: 1.0.0 +minimist: 1.2.0 +minimatch: 3.0.0 +mime-types: 2.1.7 +lru-cache: 2.7.0 +ms: 0.7.1 +mv: 2.1.1 +multipipe: 0.1.2 +nested-error-stacks: 1.0.1 +negotiator: 0.5.3 +nan: 2.1.0 +node-int64: 0.3.3 +normalize-package-data: 2.3.5 +object-assign: 3.0.0 +oauth-sign: 0.5.0 +nomnom: 1.8.1 +once: 1.3.2 +object-keys: 1.0.1 +onetime: 1.0.0 +number-is-nan: 1.0.0 +on-finished: 2.3.0 +ordered-read-streams: 0.1.0 +options: 0.0.6 +orchestrator: 0.3.7 +optionator: 0.5.0 +osenv: 0.1.3 +parse5: 1.5.0 +over: 0.0.5 +os-tmpdir: 1.0.1 +package-json: 1.2.0 +path-exists: 2.0.0 +parseurl: 1.3.0 +parse-json: 2.2.0 +path-is-inside: 1.0.1 +path-posix: 1.0.0 +path-is-absolute: 1.0.0 +os-homedir: 1.0.1 +path-to-regexp: 0.1.7 +pify: 2.3.0 +plugin-error: 0.1.2 +path-type: 1.0.0 +plist: 1.1.0 +pinkie: 1.0.0 +polyclean: 1.2.0 +pinkie-promise: 1.0.0 +precond: 0.2.3 +prepend-http: 1.0.3 +prelude-ls: 1.1.2 +process-nextick-args: 1.0.3 +pretty-hrtime: 1.0.1 +progress: 1.1.8 +pullstream: 0.4.1 +q: 1.4.1 +read-installed: 3.1.5 +proxy-addr: 1.0.8 +read-package-json: 1.3.3 +qs: 4.0.0 +read-all-stream: 3.0.1 +readable-stream: 1.1.13 +read-pkg: 1.1.0 +rechoir: 0.6.2 +range-parser: 1.0.3 +read-pkg-up: 1.0.1 +readdir-scoped-modules: 1.0.2 +replace-ext: 0.0.1 +registry-url: 3.0.3 +replacestream: 4.0.0 +redent: 1.0.0 +resolve: 1.1.6 +repeating: 2.0.0 +run-sequence: 1.1.4 +safe-json-stringify: 1.0.3 +request: 2.51.0 +send: 0.11.1 +serve-waterfall: 1.1.1 +set-immediate-shim: 1.0.1 +slide: 1.1.6 +sigmund: 1.0.1 +serve-static: 1.10.0 +server-destroy: 1.0.1 +socket.io: 1.3.7 +slice-stream: 1.0.0 +setimmediate: 1.0.4 +sntp: 0.2.4 +sparkles: 1.0.0 +socket.io-adapter: 0.3.1 +socket.io-client: 1.3.7 +socket.io-parser: 2.2.4 +spdx-exceptions: 1.0.4 +spdx-correct: 1.0.2 +source-map: 0.2.0 +sauce-connect-launcher: 0.12.0 +semver-diff: 2.0.0 +spdx-expression-parse: 1.0.1 +stream-combiner: 0.2.2 +spdx-license-ids: 1.1.0 +stacky: 1.2.3 +stream-consume: 0.1.0 +spdy: 1.32.4 +statuses: 1.2.1 +stringstream: 0.0.5 +string_decoder: 0.10.31 +stream-transform: 0.1.1 +strip-ansi: 3.0.0 +supports-color: 2.0.0 +strip-bom: 2.0.0 +through2: 2.0.0 +textextensions: 1.0.1 +through: 2.3.8 +timed-out: 2.0.0 +tar-stream: 1.1.5 +tildify: 1.1.2 +temp: 0.8.3 +string-length: 1.0.1 +traverse: 0.3.9 +trim-newlines: 1.0.0 +tough-cookie: 2.2.0 +type-check: 0.3.1 +tunnel-agent: 0.4.1 +uglify-to-browserify: 1.0.2 +unique-stream: 1.0.0 +type-is: 1.6.9 +underscore: 1.6.0 +ultron: 1.0.2 +utf-8-validate: 1.2.1 +unzip: 0.1.11 +unpipe: 1.0.0 +update-notifier: 0.5.0 +util-deprecate: 1.0.2 +utf8: 2.1.0 +urijs: 1.16.1 +uuid: 2.0.1 +utils-merge: 1.0.0 +v8flags: 2.0.10 +vargs: 0.1.0 +validate-npm-package-license: 3.0.1 +vary: 1.0.1 +vinyl: 0.5.3 +vinyl-fs: 0.3.14 +verror: 1.6.0 +wct-sauce: 1.7.1 +vasync: 1.6.3 +wct-local: 1.7.0 +underscore.string: 3.0.3 +wrappy: 1.0.1 +wordwrap: 0.0.3 +write-file-atomic: 1.1.3 +window-size: 0.1.0 +ws: 0.8.0 +xtend: 4.0.1 +xdg-basedir: 2.0.0 +xmlbuilder: 2.2.1 +zip-stream: 0.5.2 +xmldom: 0.1.19 +bower: 1.6.5 +bunyan: 1.5.1 +yargs: 3.5.4 +dateformat: 1.0.11 +espree: 2.2.5 +escodegen: 1.7.0 +gulp: 3.9.0 +har-validator: 2.0.2 +latest-version: 1.0.1 +mime: 1.3.4 +mkdirp: 0.5.1 +ncp: 2.0.0 +node-uuid: 1.4.3 +nopt: 3.0.4 +rc: 1.1.5 +rimraf: 2.4.3 +restify: 4.0.3 +semver: 4.3.6 +selenium-standalone: 4.7.1 +strip-json-comments: 1.0.4 +strip-indent: 1.0.1 +uglify-js: 2.5.0 +user-home: 1.1.1 +vulcanize: 1.14.0 +web-component-tester: 3.4.0 +which: 1.2.0 +wd: 0.3.12 REPO REVISIONS ============== -polymer: 5a755342ef6c1bd404d3b4861c3b82d10d57b2ec +polymer: 99294d92bc0be372e50cb798dd3db812df590a69 BUILD HASHES ============ -polymer-mini.html: 88f650dd1b5691577f998049967a6dc9dc456e48 -polymer-micro.html: 2261be50c3d6dfe7bd1ae9051a1115f409ef64c3 -polymer.html: 0da5e9c32e9ce759647ba6bc64618bb772890acd \ No newline at end of file +polymer-mini.html: 6800f5adc9138de2bb49d5d675e0bcb48685fcb1 +polymer-micro.html: 8bd61b7b8551b757eb2780026fee72cb18e053f5 +polymer.html: 6ed99b6c71939d49619c492ba43fc7b5a7e3a971 \ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js index 4f774b5..cdc8d66 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js
@@ -3,13 +3,13 @@ parseAnnotations: function (template) { var list = []; var content = template._content || template.content; -this._parseNodeAnnotations(content, list); +this._parseNodeAnnotations(content, list, template.hasAttribute('strip-whitespace')); return list; }, -_parseNodeAnnotations: function (node, list) { -return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list); +_parseNodeAnnotations: function (node, list, stripWhiteSpace) { +return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list, stripWhiteSpace); }, -_bindingRegex: /([^{[]*)({{|\[\[)([^}\]]*)(?:]]|}})/g, +_bindingRegex: /([^{[]*)(\{\{|\[\[)(?!\}\}|\]\])(.+?)(?:\]\]|\}\})/g, _parseBindings: function (text) { var re = this._bindingRegex; var parts = []; @@ -75,7 +75,7 @@ return annote; } }, -_parseElementAnnotations: function (element, list) { +_parseElementAnnotations: function (element, list, stripWhiteSpace) { var annote = { bindings: [], events: [] @@ -83,7 +83,7 @@ if (element.localName === 'content') { list._hasContent = true; } -this._parseChildNodesAnnotations(element, annote, list); +this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace); if (element.attributes) { this._parseNodeAttributeAnnotations(element, annote, list); if (this.prepElement) { @@ -95,26 +95,38 @@ } return annote; }, -_parseChildNodesAnnotations: function (root, annote, list, callback) { +_parseChildNodesAnnotations: function (root, annote, list, stripWhiteSpace) { if (root.firstChild) { -for (var i = 0, node = root.firstChild; node; node = node.nextSibling, i++) { +var node = root.firstChild; +var i = 0; +while (node) { +var next = node.nextSibling; if (node.localName === 'template' && !node.hasAttribute('preserve-content')) { this._parseTemplate(node, i, list, annote); } if (node.nodeType === Node.TEXT_NODE) { -var n = node.nextSibling; +var n = next; while (n && n.nodeType === Node.TEXT_NODE) { node.textContent += n.textContent; +next = n.nextSibling; root.removeChild(n); -n = n.nextSibling; +n = next; +} +if (stripWhiteSpace && !node.textContent.trim()) { +root.removeChild(node); +i--; } } -var childAnnotation = this._parseNodeAnnotations(node, list, callback); +if (node.parentNode) { +var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace); if (childAnnotation) { childAnnotation.parent = annote; childAnnotation.index = i; } } +node = next; +i++; +} } }, _parseTemplate: function (node, index, list, parent) { @@ -249,7 +261,10 @@ if (!this._template) { this._notes = []; } else { -Polymer.Annotations.prepElement = this._prepElement.bind(this); +var self = this; +Polymer.Annotations.prepElement = function (element) { +self._prepElement(element); +}; if (this._template._content && this._template._content._notes) { this._notes = this._template._content._notes; } else { @@ -296,24 +311,24 @@ }, _discoverTemplateParentProps: function (notes) { var pp = {}; -notes.forEach(function (n) { -n.bindings.forEach(function (b) { -b.parts.forEach(function (p) { +for (var i = 0, n; i < notes.length && (n = notes[i]); i++) { +for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) { +for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) { if (p.signature) { var args = p.signature.args; -for (var k = 0; k < args.length; k++) { -pp[args[k].model] = true; +for (var kk = 0; kk < args.length; kk++) { +pp[args[kk].model] = true; } } else { pp[p.model] = true; } -}); -}); +} +} if (n.templateContent) { var tpp = n.templateContent._parentProps; Polymer.Base.mixin(pp, tpp); } -}); +} return pp; }, _prepElement: function (element) { @@ -367,44 +382,46 @@ }, _marshalIdNodes: function () { this.$ = {}; -this._notes.forEach(function (a) { +for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { if (a.id) { this.$[a.id] = this._findAnnotatedNode(this.root, a); } -}, this); +} }, _marshalAnnotatedNodes: function () { -if (this._nodes) { -this._nodes = this._nodes.map(function (a) { -return this._findAnnotatedNode(this.root, a); -}, this); +if (this._notes && this._notes.length) { +var r = new Array(this._notes.length); +for (var i = 0; i < this._notes.length; i++) { +r[i] = this._findAnnotatedNode(this.root, this._notes[i]); +} +this._nodes = r; } }, _marshalAnnotatedListeners: function () { -this._notes.forEach(function (a) { +for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) { if (a.events && a.events.length) { var node = this._findAnnotatedNode(this.root, a); -a.events.forEach(function (e) { +for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) { this.listen(node, e.name, e.value); -}, this); } -}, this); +} +} } }); Polymer.Base._addFeature({ listeners: {}, _listenListeners: function (listeners) { -var node, name, key; -for (key in listeners) { -if (key.indexOf('.') < 0) { +var node, name, eventName; +for (eventName in listeners) { +if (eventName.indexOf('.') < 0) { node = this; -name = key; +name = eventName; } else { -name = key.split('.'); +name = eventName.split('.'); node = this.$[name[0]]; name = name[1]; } -this.listen(node, name, listeners[key]); +this.listen(node, name, listeners[eventName]); } }, listen: function (node, eventName, methodName) { @@ -475,6 +492,7 @@ }); (function () { 'use strict'; +var wrap = Polymer.DomApi.wrap; var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string'; var GESTURE_KEY = '__polymerGestures'; var HANDLED_OBJ = '__polymerGesturesHandled'; @@ -625,8 +643,11 @@ handleNative: function (ev) { var handled; var type = ev.type; -var node = ev.currentTarget; +var node = wrap(ev.currentTarget); var gobj = node[GESTURE_KEY]; +if (!gobj) { +return; +} var gs = gobj[type]; if (!gs) { return; @@ -709,6 +730,7 @@ } }, add: function (node, evType, handler) { +node = wrap(node); var recognizer = this.gestures[evType]; var deps = recognizer.deps; var name = recognizer.name; @@ -737,6 +759,7 @@ } }, remove: function (node, evType, handler) { +node = wrap(node); var recognizer = this.gestures[evType]; var deps = recognizer.deps; var name = recognizer.name; @@ -863,7 +886,9 @@ x: event.clientX, y: event.clientY, sourceEvent: event, -prevent: Gestures.prevent.bind(Gestures) +prevent: function (e) { +return Gestures.prevent(e); +} }); } }); @@ -1162,7 +1187,10 @@ var Async = Polymer.Async; var Debouncer = function (context) { this.context = context; -this.boundComplete = this.complete.bind(this); +var self = this; +this.boundComplete = function () { +self.complete(); +}; }; Debouncer.prototype = { go: function (callback, wait) { @@ -1263,7 +1291,7 @@ return e$ && e$[0]; }, queryAllEffectiveChildren: function (slctr) { -return Polymer.dom(this).queryAllDistributedElements(slctr); +return Polymer.dom(this).queryDistributedElements(slctr); }, getContentChildNodes: function (slctr) { var content = Polymer.dom(this.root).querySelector(slctr || 'content'); @@ -1277,19 +1305,37 @@ fire: function (type, detail, options) { options = options || Polymer.nob; var node = options.node || this; -var detail = detail === null || detail === undefined ? Polymer.nob : detail; +var detail = detail === null || detail === undefined ? {} : detail; var bubbles = options.bubbles === undefined ? true : options.bubbles; var cancelable = Boolean(options.cancelable); -var event = new CustomEvent(type, { -bubbles: Boolean(bubbles), -cancelable: cancelable, -detail: detail -}); +var useCache = options._useCache; +var event = this._getEvent(type, bubbles, cancelable, useCache); +event.detail = detail; +if (useCache) { +this.__eventCache[type] = null; +} node.dispatchEvent(event); +if (useCache) { +this.__eventCache[type] = event; +} +return event; +}, +__eventCache: {}, +_getEvent: function (type, bubbles, cancelable, useCache) { +var event = useCache && this.__eventCache[type]; +if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) { +event = new Event(type, { +bubbles: Boolean(bubbles), +cancelable: cancelable +}); +} return event; }, async: function (callback, waitTime) { -return Polymer.Async.run(callback.bind(this), waitTime); +var self = this; +return Polymer.Async.run(function () { +callback.call(self); +}, waitTime); }, cancelAsync: function (handle) { Polymer.Async.cancel(handle); @@ -1322,11 +1368,16 @@ var l = document.createElement('link'); l.rel = 'import'; l.href = href; +var self = this; if (onload) { -l.onload = onload.bind(this); +l.onload = function (e) { +return onload.call(self, e); +}; } if (onerror) { -l.onerror = onerror.bind(this); +l.onerror = function (e) { +return onerror.call(self, e); +}; } document.head.appendChild(l); return l; @@ -1348,17 +1399,18 @@ } }); Polymer.Bind = { +_dataEventCache: {}, prepareModel: function (model) { -model._propertyEffects = {}; -model._bindListeners = []; Polymer.Base.mixin(model, this._modelApi); }, _modelApi: { -_notifyChange: function (property) { -var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed'; -Polymer.Base.fire(eventName, { value: this[property] }, { +_notifyChange: function (source, event, value) { +value = value === undefined ? this[source] : value; +event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed'; +this.fire(event, { value: value }, { bubbles: false, -node: this +cancelable: false, +_useCache: true }); }, _propertySetter: function (property, value, effects, fromAbove) { @@ -1387,12 +1439,9 @@ } }, _effectEffects: function (property, value, effects, old, fromAbove) { -effects.forEach(function (fx) { -var fn = Polymer.Bind['_' + fx.kind + 'Effect']; -if (fn) { -fn.call(this, property, value, fx.effect, old, fromAbove); +for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) { +fx.fn.call(this, property, value, fx.effect, old, fromAbove); } -}, this); }, _clearPath: function (path) { for (var prop in this.__data__) { @@ -1403,6 +1452,9 @@ } }, ensurePropertyEffects: function (model, property) { +if (!model._propertyEffects) { +model._propertyEffects = {}; +} var fx = model._propertyEffects[property]; if (!fx) { fx = model._propertyEffects[property] = []; @@ -1411,10 +1463,13 @@ }, addPropertyEffect: function (model, property, kind, effect) { var fx = this.ensurePropertyEffects(model, property); -fx.push({ +var propEffect = { kind: kind, -effect: effect -}); +effect: effect, +fn: Polymer.Bind['_' + kind + 'Effect'] +}; +fx.push(propEffect); +return propEffect; }, createBindings: function (model) { var fx$ = model._propertyEffects; @@ -1464,7 +1519,10 @@ 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); +if (!model._bindListeners) { +model._bindListeners = []; +} +var fn = this._notedListenerFactory(property, path, this._isStructured(path)); var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed'; model._bindListeners.push({ index: index, @@ -1480,31 +1538,36 @@ _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); +_notedListenerFactory: function (property, path, isStructured) { +return function (target, value, targetPath) { +if (targetPath) { +this._notifyPath(this._fixPath(path, property, targetPath), value); } else { -var value = target[property]; +value = target[property]; if (!isStructured) { -this[path] = target[property]; +this[path] = value; } else { if (this.__data__[path] != value) { this.set(path, value); } } } -} }; }, prepareInstance: function (inst) { inst.__data__ = Object.create(null); }, setupBindListeners: function (inst) { -inst._bindListeners.forEach(function (info) { +var b$ = inst._bindListeners; +for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) { var node = inst._nodes[info.index]; -node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn)); +this._addNotifyListener(node, inst, info.event, info.changedFn); +} +; +}, +_addNotifyListener: function (element, context, event, changedFn) { +element.addEventListener(event, function (e) { +return context._notifyListener(changedFn, e); }); } }; @@ -1522,12 +1585,12 @@ return this._applyEffectValue(effect, calc); } }, -_reflectEffect: function (source) { -this.reflectPropertyToAttribute(source); +_reflectEffect: function (source, value, effect) { +this.reflectPropertyToAttribute(source, effect.attribute, value); }, _notifyEffect: function (source, value, effect, old, fromAbove) { if (!fromAbove) { -this._notifyChange(source); +this._notifyChange(source, effect.event, value); } }, _functionEffect: function (source, value, fn, old, fromAbove) { @@ -1613,7 +1676,8 @@ }); Polymer.Base._addFeature({ _addPropertyEffect: function (property, kind, effect) { -Polymer.Bind.addPropertyEffect(this, property, kind, effect); +var prop = Polymer.Bind.addPropertyEffect(this, property, kind, effect); +prop.pathFn = this['_' + prop.kind + 'PathEffect']; }, _prepEffects: function () { Polymer.Bind.prepareModel(this); @@ -1634,10 +1698,10 @@ this._addComputedEffect(p, prop.computed); } if (prop.notify) { -this._addPropertyEffect(p, 'notify'); +this._addPropertyEffect(p, 'notify', { event: Polymer.CaseMap.camelToDashCase(p) + '-changed' }); } if (prop.reflectToAttribute) { -this._addPropertyEffect(p, 'reflect'); +this._addPropertyEffect(p, 'reflect', { attribute: Polymer.CaseMap.camelToDashCase(p) }); } if (prop.readOnly) { Polymer.Bind.ensurePropertyEffects(this, p); @@ -1647,14 +1711,14 @@ }, _addComputedEffect: function (name, expression) { var sig = this._parseMethod(expression); -sig.args.forEach(function (arg) { +for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { this._addPropertyEffect(arg.model, 'compute', { method: sig.method, args: sig.args, trigger: arg, name: name }); -}, this); +} }, _addObserverEffect: function (property, observer) { this._addPropertyEffect(property, 'observer', { @@ -1664,29 +1728,28 @@ }, _addComplexObserverEffects: function (observers) { if (observers) { -observers.forEach(function (observer) { -this._addComplexObserverEffect(observer); -}, this); +for (var i = 0, o; i < observers.length && (o = observers[i]); i++) { +this._addComplexObserverEffect(o); +} } }, _addComplexObserverEffect: function (observer) { var sig = this._parseMethod(observer); -sig.args.forEach(function (arg) { +for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { this._addPropertyEffect(arg.model, 'complexObserver', { method: sig.method, args: sig.args, trigger: arg }); -}, this); +} }, _addAnnotationEffects: function (notes) { -this._nodes = []; -notes.forEach(function (note) { -var index = this._nodes.push(note) - 1; -note.bindings.forEach(function (binding) { -this._addAnnotationEffect(binding, index); -}, this); -}, this); +for (var i = 0, note; i < notes.length && (note = notes[i]); i++) { +var b$ = note.bindings; +for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) { +this._addAnnotationEffect(binding, i); +} +} }, _addAnnotationEffect: function (note, index) { if (Polymer.Bind._shouldAddListener(note)) { @@ -1716,11 +1779,11 @@ if (sig.static) { this.__addAnnotatedComputationEffect('__static__', index, note, part, null); } else { -sig.args.forEach(function (arg) { +for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) { if (!arg.literal) { this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg); } -}, this); +} } }, __addAnnotatedComputationEffect: function (property, index, note, part, trigger) { @@ -1799,7 +1862,9 @@ }, _marshalInstanceEffects: function () { Polymer.Bind.prepareInstance(this); +if (this._bindListeners) { Polymer.Bind.setupBindListeners(this); +} }, _applyEffectValue: function (info, value) { var node = this._nodes[info.index]; @@ -1818,11 +1883,14 @@ if (property === 'textContent' || node.localName == 'input' && property == 'value') { value = value == undefined ? '' : value; } -return node[property] = value; +var pinfo; +if (!node._propertyInfo || !(pinfo = node._propertyInfo[property]) || !pinfo.readOnly) { +this.__setProperty(property, value, true, node); +} } }, _executeStaticEffects: function () { -if (this._propertyEffects.__static__) { +if (this._propertyEffects && this._propertyEffects.__static__) { this._effectEffects('__static__', null, this._propertyEffects.__static__); } } @@ -1830,12 +1898,14 @@ Polymer.Base._addFeature({ _setupConfigure: function (initialConfig) { this._config = {}; +this._handlers = []; +if (initialConfig) { for (var i in initialConfig) { if (initialConfig[i] !== undefined) { this._config[i] = initialConfig[i]; } } -this._handlers = []; +} }, _marshalAttributes: function () { this._takeAttributesToModel(this._config); @@ -1845,7 +1915,10 @@ this._setAttributeToProperty(model, name); }, _configValue: function (name, value) { +var info = this._propertyInfo[name]; +if (!info || !info.readOnly) { this._config[name] = value; +} }, _beforeClientsReady: function () { this._configure(); @@ -1854,13 +1927,15 @@ this._configureAnnotationReferences(); this._aboveConfig = this.mixin({}, this._config); var config = {}; -this.behaviors.forEach(function (b) { -this._configureProperties(b.properties, config); -}, this); +for (var i = 0; i < this.behaviors.length; i++) { +this._configureProperties(this.behaviors[i].properties, config); +} this._configureProperties(this.properties, config); -this._mixinConfigure(config, this._aboveConfig); +this.mixin(config, this._aboveConfig); this._config = config; +if (this._clients && this._clients.length) { this._distributeConfig(this._config); +} }, _configureProperties: function (properties, config) { for (var i in properties) { @@ -1874,13 +1949,6 @@ } } }, -_mixinConfigure: function (a, b) { -for (var prop in b) { -if (!this.getPropertyInfo(prop).readOnly) { -a[prop] = b[prop]; -} -} -}, _distributeConfig: function (config) { var fx$ = this._propertyEffects; if (fx$) { @@ -1913,14 +1981,22 @@ } }, _notifyListener: function (fn, e) { +if (!Polymer.Bind._isEventBogus(e, e.target)) { +var value, path; +if (e.detail) { +value = e.detail.value; +path = e.detail.path; +} if (!this._clientsReadied) { this._queueHandler([ fn, -e, -e.target +e.target, +value, +path ]); } else { -return fn.call(this, e, e.target); +return fn.call(this, e.target, value, path); +} } }, _queueHandler: function (args) { @@ -1929,7 +2005,7 @@ _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]); +h[0].call(this, h[1], h[2], h[3]); } this._handlers = []; } @@ -2038,14 +2114,14 @@ }, _pathEffector: function (path, value) { var model = this._modelForPath(path); -var fx$ = this._propertyEffects[model]; +var fx$ = this._propertyEffects && this._propertyEffects[model]; if (fx$) { -fx$.forEach(function (fx) { -var fxFn = this['_' + fx.kind + 'PathEffect']; +for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) { +var fxFn = fx.pathFn; if (fxFn) { fxFn.call(this, path, value, fx.effect); } -}, this); +} } if (this._boundPaths) { this._notifyBoundPaths(path, value); @@ -2114,7 +2190,10 @@ this.fire(eventName, { path: path, value: value -}, { bubbles: false }); +}, { +bubbles: false, +_useCache: true +}); }, _modelForPath: function (path) { var dot = path.indexOf('.'); @@ -2217,6 +2296,8 @@ prepareModelNotifyPath: function (model) { this.mixin(model, { fire: Polymer.Base.fire, +_getEvent: Polymer.Base._getEvent, +__eventCache: Polymer.Base.__eventCache, notifyPath: Polymer.Base.notifyPath, _get: Polymer.Base._get, _EVENT_CHANGED: Polymer.Base._EVENT_CHANGED, @@ -2290,6 +2371,8 @@ if (node.parent) { var ss = node.previous ? node.previous.end : node.parent.start; t = text.substring(ss, node.start - 1); +t = this._expandUnicodeEscapes(t); +t = t.replace(this._rx.multipleSpaces, ' '); t = t.substring(t.lastIndexOf(';') + 1); var s = node.parsedSelector = node.selector = t.trim(); node.atRule = s.indexOf(this.AT_START) === 0; @@ -2315,6 +2398,15 @@ } return node; }, +_expandUnicodeEscapes: function (s) { +return s.replace(/\\([0-9a-f]{1,6})\s/gi, function () { +var code = arguments[1], repeat = 6 - code.length; +while (repeat--) { +code = '0' + code; +} +return '\\' + code; +}); +}, stringify: function (node, preserveProperties, text) { text = text || ''; var cssText = ''; @@ -2344,7 +2436,7 @@ return text; }, _hasMixinRules: function (rules) { -return rules[0].selector.indexOf(this.VAR_START) >= 0; +return rules[0].selector.indexOf(this.VAR_START) === 0; }, removeCustomProps: function (cssText) { return cssText; @@ -2369,8 +2461,9 @@ customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim, mixinProp: /(?:^|[\s;])?--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim, mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim, -varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim, -keyframesRule: /^@[^\s]*keyframes/ +varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim, +keyframesRule: /^@[^\s]*keyframes/, +multipleSpaces: /\s+/g }, VAR_START: '--', MEDIA_START: '@media', @@ -2450,21 +2543,21 @@ cssFromModule: function (moduleId, warnIfNotFound) { var m = Polymer.DomModule.import(moduleId); if (m && !m._cssText) { -m._cssText = this._cssFromElement(m); +m._cssText = this.cssFromElement(m); } if (!m && warnIfNotFound) { console.warn('Could not find style data in module named', moduleId); } return m && m._cssText || ''; }, -_cssFromElement: function (element) { +cssFromElement: function (element) { var cssText = ''; var content = element.content || element; -var e$ = Array.prototype.slice.call(content.querySelectorAll(this.MODULE_STYLES_SELECTOR)); +var e$ = Polymer.DomApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR)); for (var i = 0, e; i < e$.length; i++) { e = e$[i]; if (e.localName === 'template') { -cssText += this._cssFromElement(e); +cssText += this.cssFromElement(e); } else { if (e.localName === 'style') { var include = e.getAttribute(this.INCLUDE_ATTR); @@ -2713,7 +2806,7 @@ if (target.parent !== source.parent) { this._cloneAndAddRuleToParent(source, target.parent); } -target.extends = target.extends || (target.extends = []); +target.extends = target.extends || []; target.extends.push(source); source.selector = source.selector.replace(this.rx.STRIP, ''); source.selector = (source.selector && source.selector + ',\n') + target.selector; @@ -2754,14 +2847,18 @@ if (this._encapsulateStyle === undefined) { this._encapsulateStyle = !nativeShadow && Boolean(this._template); } +if (this._template) { this._styles = this._collectStyles(); var cssText = styleTransformer.elementStyles(this); -if (cssText && this._template) { +if (cssText) { var style = styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : null); if (!nativeShadow) { this._scopeStyle = style; } } +} else { +this._styles = []; +} }, _collectStyles: function () { var styles = []; @@ -2772,6 +2869,10 @@ } } cssText += styleUtil.cssFromModule(this.is); +var p = this._template && this._template.parentNode; +if (this._template && (!p || p.id.toLowerCase() !== this.is)) { +cssText += styleUtil.cssFromElement(this._template); +} if (cssText) { var style = document.createElement('style'); style.textContent = cssText; @@ -2805,21 +2906,21 @@ if (node.nodeType === Node.ELEMENT_NODE) { node.className = self._scopeElementClass(node, node.className); var n$ = node.querySelectorAll('*'); -Array.prototype.forEach.call(n$, function (n) { +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { n.className = self._scopeElementClass(n, n.className); -}); +} } }; scopify(container); if (shouldObserve) { var mo = new MutationObserver(function (mxns) { -mxns.forEach(function (m) { +for (var i = 0, m; i < mxns.length && (m = mxns[i]); i++) { if (m.addedNodes) { -for (var i = 0; i < m.addedNodes.length; i++) { -scopify(m.addedNodes[i]); +for (var j = 0; j < m.addedNodes.length; j++) { +scopify(m.addedNodes[j]); } } -}); +} }); mo.observe(container, { childList: true, @@ -2944,7 +3045,9 @@ parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || ''; } } -return parts.join(';'); +return parts.filter(function (v) { +return v; +}).join(';'); }, applyProperties: function (rule, props) { var output = ''; @@ -3189,9 +3292,12 @@ var nativeShadow = Polymer.Settings.useNativeShadow; Polymer.Base._addFeature({ _prepStyleProperties: function () { -this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : []; +this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : null; }, -customStyle: {}, +customStyle: null, +getComputedStyleValue: function (property) { +return this._styleProperties && this._styleProperties[property] || getComputedStyle(this).getPropertyValue(property); +}, _setupStyleProperties: function () { this.customStyle = {}; }, @@ -3288,7 +3394,7 @@ value = host._scopeElementClass(node, value); } } -node = Polymer.dom(node); +node = this.shadyRoot && this.shadyRoot._hasDistributed ? Polymer.dom(node) : node; serializeValueToAttribute.call(this, value, attribute, node); }, _scopeElementClass: function (element, selector) { @@ -3337,7 +3443,6 @@ Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); -this._prepAttributes(); this._prepConstructor(); this._prepTemplate(); this._prepStyles(); @@ -3345,6 +3450,7 @@ this._prepAnnotations(); this._prepEffects(); this._prepBehaviors(); +this._prepPropertyInfo(); this._prepBindings(); this._prepShady(); }, @@ -3354,23 +3460,28 @@ this._addHostAttributes(b.hostAttributes); }, _initFeatures: function () { -this._poolContent(); this._setupConfigure(); this._setupStyleProperties(); -this._pushHost(); -this._stampTemplate(); -this._popHost(); -this._marshalAnnotationReferences(); this._setupDebouncers(); +this._registerHost(); +if (this._template) { +this._poolContent(); +this._beginHosting(); +this._stampTemplate(); +this._endHosting(); +this._marshalAnnotationReferences(); +} this._marshalInstanceEffects(); -this._marshalHostAttributes(); this._marshalBehaviors(); +this._marshalHostAttributes(); this._marshalAttributes(); this._tryReady(); }, _marshalBehavior: function (b) { +if (b.listeners) { this._listenListeners(b.listeners); } +} }); (function () { var nativeShadow = Polymer.Settings.useNativeShadow; @@ -3382,6 +3493,7 @@ Polymer({ is: 'custom-style', extends: 'style', +_template: null, properties: { include: String }, ready: function () { this._tryApply(); @@ -3396,18 +3508,19 @@ var e = this.__appliedElement || this; styleDefaults.addStyle(e); if (e.textContent || this.include) { -this._apply(); +this._apply(true); } else { +var self = this; var observer = new MutationObserver(function () { observer.disconnect(); -this._apply(); -}.bind(this)); +self._apply(true); +}); observer.observe(e, { childList: true }); } } } }, -_apply: function () { +_apply: function (deferProperties) { var e = this.__appliedElement || this; if (this.include) { e.textContent = styleUtil.cssFromModules(this.include, true) + e.textContent; @@ -3416,7 +3529,19 @@ styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function (rule) { styleTransformer.documentRule(rule); }); -this._applyCustomProperties(e); +var self = this; +function fn() { +self._applyCustomProperties(e); +} +if (this._pendingApplyProperties) { +cancelAnimationFrame(this._pendingApplyProperties); +this._pendingApplyProperties = null; +} +if (deferProperties) { +this._pendingApplyProperties = requestAnimationFrame(fn); +} else { +fn(); +} } }, _applyCustomProperties: function (element) { @@ -3453,6 +3578,7 @@ archetype._prepEffects(); this._customPrepEffects(archetype); archetype._prepBehaviors(); +archetype._prepPropertyInfo(); archetype._prepBindings(); archetype._notifyPathUp = this._notifyPathUpImpl; archetype._scopeElementClass = this._scopeElementClassImpl; @@ -3515,7 +3641,9 @@ if (!c._notes) { var rootDataHost = archetype._rootDataHost; if (rootDataHost) { -Polymer.Annotations.prepElement = rootDataHost._prepElement.bind(rootDataHost); +Polymer.Annotations.prepElement = function () { +rootDataHost._prepElement(); +}; } c._notes = Polymer.Annotations.parseAnnotations(template); Polymer.Annotations.prepElement = null; @@ -3543,19 +3671,29 @@ var effects = [ { kind: 'function', -effect: this._createForwardPropEffector(prop) +effect: this._createForwardPropEffector(prop), +fn: Polymer.Bind._functionEffect }, -{ kind: 'notify' } +{ +kind: 'notify', +fn: Polymer.Bind._notifyEffect, +effect: { event: Polymer.CaseMap.camelToDashCase(parentProp) + '-changed' } +} ]; Polymer.Bind._createAccessors(proto, parentProp, effects); } } +var self = this; if (template != this) { Polymer.Bind.prepareInstance(template); -template._forwardParentProp = this._forwardParentProp.bind(this); +template._forwardParentProp = function (source, value) { +self._forwardParentProp(source, value); +}; } this._extendTemplate(template, proto); -template._pathEffector = this._pathEffectorImpl.bind(this); +template._pathEffector = function (path, value, fromAbove) { +return self._pathEffectorImpl(path, value, fromAbove); +}; } }, _createForwardPropEffector: function (prop) { @@ -3577,14 +3715,15 @@ }; }, _extendTemplate: function (template, proto) { -Object.getOwnPropertyNames(proto).forEach(function (n) { +var n$ = Object.getOwnPropertyNames(proto); +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { var val = template[n]; var pd = Object.getOwnPropertyDescriptor(proto, n); Object.defineProperty(template, n, pd); if (val !== undefined) { template._propertySetter(n, val); } -}); +} }, _showHideChildren: function (hidden) { }, @@ -3616,11 +3755,12 @@ _constructorImpl: function (model, host) { this._rootDataHost = host._getRootDataHost(); this._setupConfigure(model); -this._pushHost(host); +this._registerHost(host); +this._beginHosting(); this.root = this.instanceTemplate(this._template); this.root.__noContent = !this._notes._hasContent; this.root.__styleScoped = true; -this._popHost(); +this._endHosting(); this._marshalAnnotatedNodes(); this._marshalInstanceEffects(); this._marshalAnnotatedListeners(); @@ -3679,6 +3819,7 @@ Polymer({ is: 'dom-template', extends: 'template', +_template: null, behaviors: [Polymer.Templatizer], ready: function () { this.templatize(this); @@ -3779,21 +3920,21 @@ return items; }, _applySplices: function (splices) { -var keyMap = {}, key, i; -splices.forEach(function (s) { +var keyMap = {}, key; +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { s.addedKeys = []; -for (i = 0; i < s.removed.length; i++) { -key = this.getKey(s.removed[i]); +for (var j = 0; j < s.removed.length; j++) { +key = this.getKey(s.removed[j]); keyMap[key] = keyMap[key] ? null : -1; } -for (i = 0; i < s.addedCount; i++) { -var item = this.userArray[s.index + i]; +for (var j = 0; j < s.addedCount; j++) { +var item = this.userArray[s.index + j]; key = this.getKey(item); key = key === undefined ? this.add(item) : key; keyMap[key] = keyMap[key] ? null : 1; s.addedKeys.push(key); } -}, this); +} var removed = []; var added = []; for (var key in keyMap) { @@ -3821,6 +3962,7 @@ Polymer({ is: 'dom-repeat', extends: 'template', +_template: null, properties: { items: { type: Array }, as: { @@ -3843,22 +3985,37 @@ type: String, observer: '_observeChanged' }, -delay: Number +delay: Number, +initialCount: { +type: Number, +observer: '_initializeChunking' +}, +targetFramerate: { +type: Number, +value: 20 +}, +_targetFrameTime: { computed: '_computeFrameTime(targetFramerate)' } }, behaviors: [Polymer.Templatizer], observers: ['_itemsChanged(items.*)'], created: function () { this._instances = []; +this._pool = []; +this._limit = Infinity; +var self = this; +this._boundRenderChunk = function () { +self._renderChunk(); +}; }, detached: function () { for (var i = 0; i < this._instances.length; i++) { -this._detachRow(i); +this._detachInstance(i); } }, attached: function () { -var parentNode = Polymer.dom(this).parentNode; +var parent = Polymer.dom(Polymer.dom(this).parentNode); for (var i = 0; i < this._instances.length; i++) { -Polymer.dom(parentNode).insertBefore(this._instances[i].root, this); +this._attachInstance(i, parent); } }, ready: function () { @@ -3869,9 +4026,8 @@ this.templatize(this); } }, -_sortChanged: function () { +_sortChanged: function (sort) { var dataHost = this._getRootDataHost(); -var sort = this.sort; this._sortFn = sort && (typeof sort == 'function' ? sort : function () { return dataHost[sort].apply(dataHost, arguments); }); @@ -3880,9 +4036,8 @@ this._debounceTemplate(this._render); } }, -_filterChanged: function () { +_filterChanged: function (filter) { var dataHost = this._getRootDataHost(); -var filter = this.filter; this._filterFn = filter && (typeof filter == 'function' ? filter : function () { return dataHost[filter].apply(dataHost, arguments); }); @@ -3891,6 +4046,32 @@ this._debounceTemplate(this._render); } }, +_computeFrameTime: function (rate) { +return Math.ceil(1000 / rate); +}, +_initializeChunking: function () { +if (this.initialCount) { +this._limit = this.initialCount; +this._chunkCount = this.initialCount; +this._lastChunkTime = performance.now(); +} +}, +_tryRenderChunk: function () { +if (this.items && this._limit < this.items.length) { +this.debounce('renderChunk', this._requestRenderChunk); +} +}, +_requestRenderChunk: function () { +requestAnimationFrame(this._boundRenderChunk); +}, +_renderChunk: function () { +var currChunkTime = performance.now(); +var ratio = this._targetFrameTime / (currChunkTime - this._lastChunkTime); +this._chunkCount = Math.round(this._chunkCount * ratio) || 1; +this._limit += this._chunkCount; +this._lastChunkTime = currChunkTime; +this._debounceTemplate(this._render); +}, _observeChanged: function () { this._observePaths = this.observe && this.observe.replace('.*', '.').split(' '); }, @@ -3906,6 +4087,7 @@ this._keySplices = []; this._indexSplices = []; this._needFullRefresh = true; +this._initializeChunking(); this._debounceTemplate(this._render); } else if (change.path == 'items.splices') { this._keySplices = this._keySplices.concat(change.value.keySplices); @@ -3944,7 +4126,7 @@ if (this._needFullRefresh) { this._applyFullRefresh(); this._needFullRefresh = false; -} else { +} else if (this._keySplices.length) { if (this._sortFn) { this._applySplicesUserSort(this._keySplices); } else { @@ -3954,16 +4136,26 @@ this._applySplicesArrayOrder(this._indexSplices); } } +} else { } this._keySplices = []; this._indexSplices = []; var keyToIdx = this._keyToInstIdx = {}; -for (var i = 0; i < this._instances.length; i++) { +for (var i = this._instances.length - 1; i >= 0; i--) { var inst = this._instances[i]; +if (inst.isPlaceholder && i < this._limit) { +inst = this._insertInstance(i, inst.__key__); +} else if (!inst.isPlaceholder && i >= this._limit) { +inst = this._downgradeInstance(i, inst.__key__); +} keyToIdx[inst.__key__] = i; +if (!inst.isPlaceholder) { inst.__setProperty(this.indexAs, i, true); } +} +this._pool.length = 0; this.fire('dom-change'); +this._tryRenderChunk(); }, _applyFullRefresh: function () { var c = this.collection; @@ -3979,33 +4171,34 @@ } } } +var self = this; if (this._filterFn) { keys = keys.filter(function (a) { -return this._filterFn(c.getItem(a)); -}, this); +return self._filterFn(c.getItem(a)); +}); } if (this._sortFn) { keys.sort(function (a, b) { -return this._sortFn(c.getItem(a), c.getItem(b)); -}.bind(this)); +return self._sortFn(c.getItem(a), c.getItem(b)); +}); } for (var i = 0; i < keys.length; i++) { var key = keys[i]; var inst = this._instances[i]; if (inst) { -inst.__setProperty('__key__', key, true); +inst.__key__ = key; +if (!inst.isPlaceholder && i < this._limit) { inst.__setProperty(this.as, c.getItem(key), true); +} +} else if (i < this._limit) { +this._insertInstance(i, key); } else { -this._instances.push(this._insertRow(i, key)); +this._insertPlaceholder(i, key); } } -for (; i < this._instances.length; i++) { -this._detachRow(i); +for (var j = this._instances.length - 1; j >= i; j--) { +this._detachAndRemoveInstance(j); } -this._instances.splice(keys.length, this._instances.length - keys.length); -}, -_keySort: function (a, b) { -return this.collection.getKey(a) - this.collection.getKey(b); }, _numericSort: function (a, b) { return a - b; @@ -4014,18 +4207,16 @@ var c = this.collection; var instances = this._instances; var keyMap = {}; -var pool = []; -var sortFn = this._sortFn || this._keySort.bind(this); -splices.forEach(function (s) { -for (var i = 0; i < s.removed.length; i++) { -var key = s.removed[i]; +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { +for (var j = 0; j < s.removed.length; j++) { +var key = s.removed[j]; keyMap[key] = keyMap[key] ? null : -1; } -for (var i = 0; i < s.added.length; i++) { -var key = s.added[i]; +for (var j = 0; j < s.added.length; j++) { +var key = s.added[j]; keyMap[key] = keyMap[key] ? null : 1; } -}, this); +} var removedIdxs = []; var addedKeys = []; for (var key in keyMap) { @@ -4041,36 +4232,35 @@ for (var i = removedIdxs.length - 1; i >= 0; i--) { var idx = removedIdxs[i]; if (idx !== undefined) { -pool.push(this._detachRow(idx)); -instances.splice(idx, 1); +this._detachAndRemoveInstance(idx); } } } +var self = this; if (addedKeys.length) { if (this._filterFn) { addedKeys = addedKeys.filter(function (a) { -return this._filterFn(c.getItem(a)); -}, this); +return self._filterFn(c.getItem(a)); +}); } addedKeys.sort(function (a, b) { -return this._sortFn(c.getItem(a), c.getItem(b)); -}.bind(this)); +return self._sortFn(c.getItem(a), c.getItem(b)); +}); var start = 0; for (var i = 0; i < addedKeys.length; i++) { -start = this._insertRowUserSort(start, addedKeys[i], pool); +start = this._insertRowUserSort(start, addedKeys[i]); } } }, -_insertRowUserSort: function (start, key, pool) { +_insertRowUserSort: function (start, key) { var c = this.collection; var item = c.getItem(key); var end = this._instances.length - 1; var idx = -1; -var sortFn = this._sortFn || this._keySort.bind(this); while (start <= end) { var mid = start + end >> 1; var midKey = this._instances[mid].__key__; -var cmp = sortFn(c.getItem(midKey), item); +var cmp = this._sortFn(c.getItem(midKey), item); if (cmp < 0) { start = mid + 1; } else if (cmp > 0) { @@ -4083,65 +4273,80 @@ if (idx < 0) { idx = end + 1; } -this._instances.splice(idx, 0, this._insertRow(idx, key, pool)); +this._insertPlaceholder(idx, key); return idx; }, _applySplicesArrayOrder: function (splices) { -var pool = []; var c = this.collection; -splices.forEach(function (s) { -for (var i = 0; i < s.removed.length; i++) { -var inst = this._detachRow(s.index + i); -if (!inst.isPlaceholder) { -pool.push(inst); +for (var i = 0, s; i < splices.length && (s = splices[i]); i++) { +for (var j = 0; j < s.removed.length; j++) { +this._detachAndRemoveInstance(s.index); } -} -this._instances.splice(s.index, s.removed.length); -for (var i = 0; i < s.addedKeys.length; i++) { -var inst = { -isPlaceholder: true, -key: s.addedKeys[i] -}; -this._instances.splice(s.index + i, 0, inst); -} -}, this); -for (var i = this._instances.length - 1; i >= 0; i--) { -var inst = this._instances[i]; -if (inst.isPlaceholder) { -this._instances[i] = this._insertRow(i, inst.key, pool, true); +for (var j = 0; j < s.addedKeys.length; j++) { +this._insertPlaceholder(s.index + j, s.addedKeys[j]); } } }, -_detachRow: function (idx) { +_detachInstance: function (idx) { var inst = this._instances[idx]; if (!inst.isPlaceholder) { -var parentNode = Polymer.dom(this).parentNode; for (var i = 0; i < inst._children.length; i++) { var el = inst._children[i]; Polymer.dom(inst.root).appendChild(el); } -} return inst; -}, -_insertRow: function (idx, key, pool, replace) { -var inst; -if (inst = pool && pool.pop()) { -inst.__setProperty(this.as, this.collection.getItem(key), true); -inst.__setProperty('__key__', key, true); -} else { -inst = this._generateRow(idx, key); } -var beforeRow = this._instances[replace ? idx + 1 : idx]; -var beforeNode = beforeRow ? beforeRow._children[0] : this; -var parentNode = Polymer.dom(this).parentNode; -Polymer.dom(parentNode).insertBefore(inst.root, beforeNode); -return inst; }, -_generateRow: function (idx, key) { +_attachInstance: function (idx, parent) { +var inst = this._instances[idx]; +if (!inst.isPlaceholder) { +parent.insertBefore(inst.root, this); +} +}, +_detachAndRemoveInstance: function (idx) { +var inst = this._detachInstance(idx); +if (inst) { +this._pool.push(inst); +} +this._instances.splice(idx, 1); +}, +_insertPlaceholder: function (idx, key) { +this._instances.splice(idx, 0, { +isPlaceholder: true, +__key__: key +}); +}, +_stampInstance: function (idx, key) { var model = { __key__: key }; model[this.as] = this.collection.getItem(key); model[this.indexAs] = idx; -var inst = this.stamp(model); +return this.stamp(model); +}, +_insertInstance: function (idx, key) { +var inst = this._pool.pop(); +if (inst) { +inst.__setProperty(this.as, this.collection.getItem(key), true); +inst.__setProperty('__key__', key, true); +} else { +inst = this._stampInstance(idx, key); +} +var beforeRow = this._instances[idx + 1]; +var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this; +var parentNode = Polymer.dom(this).parentNode; +Polymer.dom(parentNode).insertBefore(inst.root, beforeNode); +this._instances[idx] = inst; +return inst; +}, +_downgradeInstance: function (idx, key) { +var inst = this._detachInstance(idx); +if (inst) { +this._pool.push(inst); +} +inst = { +isPlaceholder: true, +__key__: key +}; +this._instances[idx] = inst; return inst; }, _showHideChildren: function (hidden) { @@ -4166,14 +4371,20 @@ } }, _forwardParentProp: function (prop, value) { -this._instances.forEach(function (inst) { +var i$ = this._instances; +for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) { +if (!inst.isPlaceholder) { inst.__setProperty(prop, value, true); -}, this); +} +} }, _forwardParentPath: function (path, value) { -this._instances.forEach(function (inst) { +var i$ = this._instances; +for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) { +if (!inst.isPlaceholder) { inst._notifyPath(path, value, true); -}, this); +} +} }, _forwardItemPath: function (path, value) { if (this._keyToInstIdx) { @@ -4181,7 +4392,7 @@ var key = path.substring(0, dot < 0 ? path.length : dot); var idx = this._keyToInstIdx[key]; var inst = this._instances[idx]; -if (inst) { +if (inst && !inst.isPlaceholder) { if (dot >= 0) { path = this.as + '.' + path.substring(dot + 1); inst._notifyPath(path, value, true); @@ -4206,6 +4417,7 @@ }); Polymer({ is: 'array-selector', +_template: null, properties: { items: { type: Array, @@ -4298,6 +4510,7 @@ Polymer({ is: 'dom-if', extends: 'template', +_template: null, properties: { 'if': { type: Boolean, @@ -4345,20 +4558,23 @@ }, _ensureInstance: function () { if (!this._instance) { +var parentNode = Polymer.dom(this).parentNode; +if (parentNode) { +var parent = Polymer.dom(parentNode); this._instance = this.stamp(); var root = this._instance.root; -var parent = Polymer.dom(Polymer.dom(this).parentNode); parent.insertBefore(root, this); } +} }, _teardownInstance: function () { if (this._instance) { -var c = this._instance._children; -if (c) { -var parent = Polymer.dom(Polymer.dom(c[0]).parentNode); -c.forEach(function (n) { +var c$ = this._instance._children; +if (c$) { +var parent = Polymer.dom(Polymer.dom(c$[0]).parentNode); +for (var i = 0, n; i < c$.length && (n = c$[i]); i++) { parent.removeChild(n); -}); +} } this._instance = null; } @@ -4383,8 +4599,12 @@ Polymer({ is: 'dom-bind', extends: 'template', +_template: null, created: function () { -Polymer.RenderStatus.whenReady(this._markImportsReady.bind(this)); +var self = this; +Polymer.RenderStatus.whenReady(function () { +self._markImportsReady(); +}); }, _ensureReady: function () { if (!this._readied) { @@ -4423,7 +4643,10 @@ for (var prop in this._propertyEffects) { config[prop] = this[prop]; } -this._setupConfigure = this._setupConfigure.bind(this, config); +var setupConfigure = this._setupConfigure; +this._setupConfigure = function () { +setupConfigure.call(this, config); +}; }, attached: function () { if (this._importsReady) { @@ -4442,8 +4665,9 @@ this._prepBehaviors(); this._prepConfigure(); this._prepBindings(); +this._prepPropertyInfo(); Polymer.Base._initFeatures.call(this); -this._children = Array.prototype.slice.call(this.root.childNodes); +this._children = Polymer.DomApi.arrayCopyChildNodes(this.root); } this._insertChildren(); this.fire('dom-change');
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js index 889a234..95d8736d 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js
@@ -15,10 +15,11 @@ window.Polymer = { Settings: function () { var user = window.Polymer || {}; -location.search.slice(1).split('&').forEach(function (o) { +var parts = location.search.slice(1).split('&'); +for (var i = 0, o; i < parts.length && (o = parts[i]); i++) { 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; @@ -105,15 +106,53 @@ }, _makeReady: function () { this._ready = true; -this._callbacks.forEach(function (cb) { -cb(); -}); +for (var i = 0; i < this._callbacks.length; i++) { +this._callbacks[i](); +} this._callbacks = []; }, _catchFirstRender: function () { requestAnimationFrame(function () { Polymer.RenderStatus._makeReady(); }); +}, +_afterNextRenderQueue: [], +_waitingNextRender: false, +afterNextRender: function (element, fn, args) { +this._watchNextRender(); +this._afterNextRenderQueue.push([ +element, +fn, +args +]); +}, +_watchNextRender: function () { +if (!this._waitingNextRender) { +this._waitingNextRender = true; +var fn = function () { +Polymer.RenderStatus._flushNextRender(); +}; +if (!this._ready) { +this.whenReady(fn); +} else { +requestAnimationFrame(fn); +} +} +}, +_flushNextRender: function () { +var self = this; +setTimeout(function () { +self._flushRenderCallbacks(self._afterNextRenderQueue); +self._afterNextRenderQueue = []; +self._waitingNextRender = false; +}); +}, +_flushRenderCallbacks: function (callbacks) { +for (var i = 0, h; i < callbacks.length; i++) { +h = callbacks[i]; +h[1].apply(h[0], h[2] || Polymer.nar); +} +; } }; if (window.HTMLImports) { @@ -143,27 +182,33 @@ this._initFeatures(); }, attachedCallback: function () { +var self = this; Polymer.RenderStatus.whenReady(function () { -this.isAttached = true; -this._doBehavior('attached'); -}.bind(this)); +self.isAttached = true; +self._doBehavior('attached'); +}); }, detachedCallback: function () { this.isAttached = false; this._doBehavior('detached'); }, -attributeChangedCallback: function (name) { +attributeChangedCallback: function (name, oldValue, newValue) { this._attributeChangedImpl(name); -this._doBehavior('attributeChanged', arguments); +this._doBehavior('attributeChanged', [ +name, +oldValue, +newValue +]); }, _attributeChangedImpl: function (name) { this._setAttributeToProperty(this, name); }, extend: function (prototype, api) { if (prototype && api) { -Object.getOwnPropertyNames(api).forEach(function (n) { +var n$ = Object.getOwnPropertyNames(api); +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { this.copyOwnProperty(n, api, prototype); -}, this); +} } return prototype || api; }, @@ -241,7 +286,7 @@ if (id) { var m = findModule(id); if (!m) { -forceDocumentUpgrade(); +forceDomModulesUpgrade(); m = findModule(id); } if (m && selector) { @@ -253,12 +298,17 @@ }); var cePolyfill = window.CustomElements && !CustomElements.useNative; document.registerElement('dom-module', DomModule); -function forceDocumentUpgrade() { +function forceDomModulesUpgrade() { if (cePolyfill) { var script = document._currentScript || document.currentScript; var doc = script && script.ownerDocument || document; -if (doc) { -CustomElements.upgradeAll(doc); +var modules = doc.querySelectorAll('dom-module'); +for (var i = modules.length - 1, m; i >= 0 && (m = modules[i]); i--) { +if (m.__upgraded__) { +return; +} else { +CustomElements.upgrade(m); +} } } } @@ -293,7 +343,8 @@ }, _flattenBehaviorsList: function (behaviors) { var flat = []; -behaviors.forEach(function (b) { +for (var i = 0; i < behaviors.length; i++) { +var b = behaviors[i]; if (b instanceof Array) { flat = flat.concat(this._flattenBehaviorsList(b)); } else if (b) { @@ -301,31 +352,16 @@ } else { this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import')); } -}, this); +} return flat; }, _mixinBehavior: function (b) { -Object.getOwnPropertyNames(b).forEach(function (n) { -switch (n) { -case 'hostAttributes': -case 'registered': -case 'properties': -case 'observers': -case 'listeners': -case 'created': -case 'attached': -case 'detached': -case 'attributeChanged': -case 'configure': -case 'ready': -break; -default: -if (!this.hasOwnProperty(n)) { +var n$ = Object.getOwnPropertyNames(b); +for (var i = 0, n; i < n$.length && (n = n$[i]); i++) { +if (!Polymer.Base._behaviorProperties[n] && !this.hasOwnProperty(n)) { this.copyOwnProperty(n, b, this); } -break; } -}, this); }, _prepBehaviors: function () { this._prepFlattenedBehaviors(this.behaviors); @@ -337,9 +373,9 @@ this._prepBehavior(this); }, _doBehavior: function (name, args) { -this.behaviors.forEach(function (b) { -this._invokeBehavior(b, name, args); -}, this); +for (var i = 0; i < this.behaviors.length; i++) { +this._invokeBehavior(this.behaviors[i], name, args); +} this._invokeBehavior(this, name, args); }, _invokeBehavior: function (b, name, args) { @@ -349,12 +385,24 @@ } }, _marshalBehaviors: function () { -this.behaviors.forEach(function (b) { -this._marshalBehavior(b); -}, this); +for (var i = 0; i < this.behaviors.length; i++) { +this._marshalBehavior(this.behaviors[i]); +} this._marshalBehavior(this); } }); +Polymer.Base._behaviorProperties = { +hostAttributes: true, +registered: true, +properties: true, +observers: true, +listeners: true, +created: true, +attached: true, +detached: true, +attributeChanged: true, +ready: true +}; Polymer.Base._addFeature({ _getExtendedPrototype: function (tag) { return this._getExtendedNativePrototype(tag); @@ -406,9 +454,13 @@ 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); +for (var i = 0; i < this.behaviors.length; i++) { +info = this._getPropertyInfo(property, this.behaviors[i].properties); +if (info) { +return info; +} +} +; } return info || Polymer.nob; }, @@ -421,6 +473,40 @@ p.defined = true; } return p; +}, +_prepPropertyInfo: function () { +this._propertyInfo = {}; +for (var i = 0, p; i < this.behaviors.length; i++) { +this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties); +} +this._addPropertyInfo(this._propertyInfo, this.properties); +this._addPropertyInfo(this._propertyInfo, this._propertyEffects); +}, +_addPropertyInfo: function (target, source) { +if (source) { +var t, s; +for (var i in source) { +t = target[i]; +s = source[i]; +if (i[0] === '_' && !s.readOnly) { +continue; +} +if (!target[i]) { +target[i] = { +type: typeof s === 'function' ? s : s.type, +readOnly: s.readOnly, +attribute: Polymer.CaseMap.camelToDashCase(i) +}; +} else { +if (!t.type) { +t.type = s.type; +} +if (!t.readOnly) { +t.readOnly = s.readOnly; +} +} +} +} } }); Polymer.CaseMap = { @@ -448,21 +534,24 @@ } }; Polymer.Base._addFeature({ -_prepAttributes: function () { -this._aggregatedAttributes = {}; -}, _addHostAttributes: function (attributes) { +if (!this._aggregatedAttributes) { +this._aggregatedAttributes = {}; +} if (attributes) { this.mixin(this._aggregatedAttributes, attributes); } }, _marshalHostAttributes: function () { +if (this._aggregatedAttributes) { this._applyAttributes(this, this._aggregatedAttributes); +} }, _applyAttributes: function (node, attr$) { for (var n in attr$) { if (!this.hasAttribute(n) && n !== 'class') { -this.serializeValueToAttribute(attr$[n], n, this); +var v = attr$[n]; +this.serializeValueToAttribute(v, n, this); } } }, @@ -470,29 +559,40 @@ this._takeAttributesToModel(this); }, _takeAttributesToModel: function (model) { -for (var i = 0, l = this.attributes.length; i < l; i++) { -this._setAttributeToProperty(model, this.attributes[i].name); +if (this.hasAttributes()) { +for (var i in this._propertyInfo) { +var info = this._propertyInfo[i]; +if (this.hasAttribute(info.attribute)) { +this._setAttributeToProperty(model, info.attribute, i, info); +} +} } }, -_setAttributeToProperty: function (model, attrName) { +_setAttributeToProperty: function (model, attribute, property, info) { if (!this._serializing) { -var propName = Polymer.CaseMap.dashToCamelCase(attrName); -var info = this.getPropertyInfo(propName); -if (info.defined || this._propertyEffects && this._propertyEffects[propName]) { -var val = this.getAttribute(attrName); -model[propName] = this.deserialize(val, info.type); +var property = property || Polymer.CaseMap.dashToCamelCase(attribute); +info = info || this._propertyInfo && this._propertyInfo[property]; +if (info && !info.readOnly) { +var v = this.getAttribute(attribute); +model[property] = this.deserialize(v, info.type); } } }, _serializing: false, -reflectPropertyToAttribute: function (name) { +reflectPropertyToAttribute: function (property, attribute, value) { this._serializing = true; -this.serializeValueToAttribute(this[name], Polymer.CaseMap.camelToDashCase(name)); +value = value === undefined ? this[property] : value; +this.serializeValueToAttribute(value, attribute || Polymer.CaseMap.camelToDashCase(property)); this._serializing = false; }, serializeValueToAttribute: function (value, attribute, node) { var str = this.serialize(value); -(node || this)[str === undefined ? 'removeAttribute' : 'setAttribute'](attribute, str); +node = node || this; +if (str === undefined) { +node.removeAttribute(attribute); +} else { +node.setAttribute(attribute, str); +} }, deserialize: function (value, type) { switch (type) { @@ -568,13 +668,13 @@ } } }); -Polymer.version = '1.2.1'; +Polymer.version = '1.2.3'; Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); -this._prepAttributes(); this._prepBehaviors(); this._prepConstructor(); +this._prepPropertyInfo(); }, _prepBehavior: function (b) { this._addHostAttributes(b.hostAttributes);
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js index e1e62f6..a34346f7 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js
@@ -1,12 +1,13 @@ Polymer.Base._addFeature({ _prepTemplate: function () { -this._template = this._template || Polymer.DomModule.import(this.is, 'template'); +if (this._template === undefined) { +this._template = Polymer.DomModule.import(this.is, 'template'); +} if (this._template && this._template.hasAttribute('is')) { this._warn(this._logf('_prepTemplate', 'top-level Polymer template ' + 'must not be a type-extension, found', this._template, 'Move inside simple <template>.')); } -if (this._template && !this._template.content && HTMLTemplateElement.bootstrap) { +if (this._template && !this._template.content && window.HTMLTemplateElement && HTMLTemplateElement.decorate) { HTMLTemplateElement.decorate(this._template); -HTMLTemplateElement.bootstrap(this._template.content); } }, _stampTemplate: function () { @@ -25,20 +26,19 @@ _hostStack: [], ready: function () { }, -_pushHost: function (host) { +_registerHost: function (host) { this.dataHost = host = host || Polymer.Base._hostStack[Polymer.Base._hostStack.length - 1]; if (host && host._clients) { host._clients.push(this); } -this._beginHost(); }, -_beginHost: function () { +_beginHosting: function () { Polymer.Base._hostStack.push(this); if (!this._clients) { this._clients = []; } }, -_popHost: function () { +_endHosting: function () { Polymer.Base._hostStack.pop(); }, _tryReady: function () { @@ -51,20 +51,24 @@ }, _ready: function () { this._beforeClientsReady(); +if (this._template) { this._setupRoot(); this._readyClients(); +} +this._clientsReadied = true; +this._clients = null; this._afterClientsReady(); this._readySelf(); }, _readyClients: function () { this._beginDistribute(); var c$ = this._clients; +if (c$) { for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) { c._ready(); } +} this._finishDistribute(); -this._clientsReadied = true; -this._clients = null; }, _readySelf: function () { this._doBehavior('ready'); @@ -367,20 +371,16 @@ var nativeAppendChild = Element.prototype.appendChild; var nativeCloneNode = Element.prototype.cloneNode; var nativeImportNode = Document.prototype.importNode; +var needsToWrap = Settings.hasShadow && !Settings.nativeShadow; +var wrap = window.wrap ? window.wrap : function (node) { +return node; +}; var DomApi = function (node) { -this.node = node; +this.node = needsToWrap ? wrap(node) : node; if (this.patch) { this.patch(); } }; -if (window.wrap && Settings.useShadow && !Settings.useNativeShadow) { -DomApi = function (node) { -this.node = wrap(node); -if (this.patch) { -this.patch(); -} -}; -} DomApi.prototype = { flush: function () { Polymer.dom.flush(); @@ -615,7 +615,7 @@ var children = factory(container).childNodes; index = index === undefined ? children.length : index; if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { -var c$ = Array.prototype.slice.call(node.childNodes); +var c$ = arrayCopyChildNodes(node); for (var i = 0, n; i < c$.length && (n = c$[i]); i++) { children.splice(index++, 0, n); n._lightParent = container; @@ -777,7 +777,7 @@ childNodes: { get: function () { var c$ = getLightChildren(this.node); -return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$); +return Array.isArray(c$) ? c$ : arrayCopyChildNodes(this.node); }, configurable: true }, @@ -900,7 +900,7 @@ this._clear(); var d = document.createElement('div'); d.innerHTML = text; -var c$ = Array.prototype.slice.call(d.childNodes); +var c$ = arrayCopyChildNodes(d); for (var i = 0; i < c$.length; i++) { this.appendChild(c$[i]); } @@ -913,20 +913,25 @@ return getInnerHTML(this.node, true); }; } else { -var forwardMethods = [ +var forwardMethods = function (m$) { +for (var i = 0; i < m$.length; i++) { +forwardMethod(m$[i]); +} +}; +var forwardMethod = function (method) { +DomApi.prototype[method] = function () { +return this.node[method].apply(this.node, arguments); +}; +}; +forwardMethods([ 'cloneNode', 'appendChild', 'insertBefore', 'removeChild', 'replaceChild' -]; -forwardMethods.forEach(function (name) { -DomApi.prototype[name] = function () { -return this.node[name].apply(this.node, arguments); -}; -}); +]); DomApi.prototype.querySelectorAll = function (selector) { -return Array.prototype.slice.call(this.node.querySelectorAll(selector)); +return arrayCopy(this.node.querySelectorAll(selector)); }; DomApi.prototype.getOwnerRoot = function () { var n = this.node; @@ -943,35 +948,24 @@ }; DomApi.prototype.getDestinationInsertionPoints = function () { var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInsertionPoints(); -return n$ ? Array.prototype.slice.call(n$) : []; +return n$ ? arrayCopy(n$) : []; }; DomApi.prototype.getDistributedNodes = function () { var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes(); -return n$ ? Array.prototype.slice.call(n$) : []; +return n$ ? arrayCopy(n$) : []; }; DomApi.prototype._distributeParent = function () { }; -var nativeForwards = [ -'appendChild', -'insertBefore', -'removeChild', -'replaceChild' -]; -nativeForwards.forEach(function (forward) { -DomApi.prototype[forward] = function () { -return this.node[forward].apply(this.node, arguments); -}; -}); Object.defineProperties(DomApi.prototype, { childNodes: { get: function () { -return Array.prototype.slice.call(this.node.childNodes); +return arrayCopyChildNodes(this.node); }, configurable: true }, children: { get: function () { -return Array.prototype.slice.call(this.node.children); +return arrayCopyChildren(this.node); }, configurable: true }, @@ -994,7 +988,20 @@ configurable: true } }); -var forwardProperties = [ +var forwardProperties = function (f$) { +for (var i = 0; i < f$.length; i++) { +forwardProperty(f$[i]); +} +}; +var forwardProperty = function (name) { +Object.defineProperty(DomApi.prototype, name, { +get: function () { +return this.node[name]; +}, +configurable: true +}); +}; +forwardProperties([ 'parentNode', 'firstChild', 'lastChild', @@ -1004,15 +1011,7 @@ 'lastElementChild', 'nextElementSibling', 'previousElementSibling' -]; -forwardProperties.forEach(function (name) { -Object.defineProperty(DomApi.prototype, name, { -get: function () { -return this.node[name]; -}, -configurable: true -}); -}); +]); } var CONTENT = 'content'; function factory(node, patch) { @@ -1026,6 +1025,7 @@ function hasDomApi(node) { return Boolean(node.__domApi); } +; Polymer.dom = function (obj, patch) { if (obj instanceof Event) { return Polymer.EventApi.factory(obj); @@ -1039,7 +1039,7 @@ } function getComposedChildren(node) { if (!node._composedChildren) { -node._composedChildren = Array.prototype.slice.call(node.childNodes); +node._composedChildren = arrayCopyChildNodes(node); } return node._composedChildren; } @@ -1075,13 +1075,35 @@ } function saveLightChildrenIfNeeded(node) { if (!node._lightChildren) { -var c$ = Array.prototype.slice.call(node.childNodes); +var c$ = arrayCopyChildNodes(node); for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) { child._lightParent = child._lightParent || node; } node._lightChildren = c$; } } +function arrayCopyChildNodes(parent) { +var copy = [], i = 0; +for (var n = parent.firstChild; n; n = n.nextSibling) { +copy[i++] = n; +} +return copy; +} +function arrayCopyChildren(parent) { +var copy = [], i = 0; +for (var n = parent.firstElementChild; n; n = n.nextElementSibling) { +copy[i++] = n; +} +return copy; +} +function arrayCopy(a$) { +var l = a$.length; +var copy = new Array(l); +for (var i = 0; i < l; i++) { +copy[i] = a$[i]; +} +return copy; +} function hasInsertionPoint(root) { return Boolean(root && root._insertionPoints.length); } @@ -1097,7 +1119,11 @@ hasInsertionPoint: hasInsertionPoint, ctor: DomApi, factory: factory, -hasDomApi: hasDomApi +hasDomApi: hasDomApi, +arrayCopy: arrayCopy, +arrayCopyChildNodes: arrayCopyChildNodes, +arrayCopyChildren: arrayCopyChildren, +wrap: wrap }; }(); Polymer.Base.extend(Polymer.dom, { @@ -1318,7 +1344,10 @@ } }, _observeContent: function (content) { -var h = Polymer.dom(content).observeNodes(this._scheduleNotify.bind(this)); +var self = this; +var h = Polymer.dom(content).observeNodes(function () { +self._scheduleNotify(); +}); h._avoidChangeCalculation = true; return h; }, @@ -1395,7 +1424,9 @@ } }; this._observer = new MutationObserver(this._mutationHandler); -this._boundFlush = this._flush.bind(this); +this._boundFlush = function () { +self._flush(); +}; Polymer.dom.addStaticFlush(this._boundFlush); this._observer.observe(this.node, { childList: true }); } @@ -1464,7 +1495,10 @@ var root = this.domApi.getOwnerRoot(); var host = root && root.host; if (host) { -this._observer = Polymer.dom(host).observeNodes(this._scheduleNotify.bind(this)); +var self = this; +this._observer = Polymer.dom(host).observeNodes(function () { +self._scheduleNotify(); +}); this._observer._isContentListener = true; if (this._hasAttrSelect()) { Polymer.dom(host).observer.enableShadowAttributeTracking(); @@ -1509,6 +1543,7 @@ _createLocalRoot: function () { this.shadyRoot = this.root; this.shadyRoot._distributionClean = false; +this.shadyRoot._hasDistributed = false; this.shadyRoot._isShadyRoot = true; this.shadyRoot._dirtyRoots = []; var i$ = this.shadyRoot._insertionPoints = !this._notes || this._notes._hasContent ? this.shadyRoot.querySelectorAll('content') : []; @@ -1835,20 +1870,23 @@ Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); -this._prepAttributes(); this._prepBehaviors(); this._prepConstructor(); this._prepTemplate(); this._prepShady(); +this._prepPropertyInfo(); }, _prepBehavior: function (b) { this._addHostAttributes(b.hostAttributes); }, _initFeatures: function () { +this._registerHost(); +if (this._template) { this._poolContent(); -this._pushHost(); +this._beginHosting(); this._stampTemplate(); -this._popHost(); +this._endHosting(); +} this._marshalHostAttributes(); this._setupDebouncers(); this._marshalBehaviors();
diff --git a/third_party/sqlite/BUILD.gn b/third_party/sqlite/BUILD.gn index 76b92153..395bfa57 100644 --- a/third_party/sqlite/BUILD.gn +++ b/third_party/sqlite/BUILD.gn
@@ -36,6 +36,7 @@ visibility = [ ":*" ] sources = [ + "amalgamation/config.h", "amalgamation/sqlite3.c", "amalgamation/sqlite3.h", ] @@ -122,15 +123,10 @@ ] } - # SQLite wants to track malloc sizes. On OSX it uses malloc_size(), on - # Windows _msize(), elsewhere it handles it manually by enlarging the malloc - # and injecting a field. Enable malloc_usable_size() for Linux. - # NOTE(shess): Android does _not_ export malloc_usable_size(). + # Pull in config.h on Linux. This allows use of preprocessor macros which + # are not available to the build config. if (is_linux) { - defines += [ - "HAVE_MALLOC_H", - "HAVE_MALLOC_USABLE_SIZE", - ] + defines += [ "_HAVE_SQLITE_CONFIG_H" ] } include_dirs = [ "amalgamation" ]
diff --git a/third_party/sqlite/amalgamation/config.h b/third_party/sqlite/amalgamation/config.h new file mode 100644 index 0000000..58941b45 --- /dev/null +++ b/third_party/sqlite/amalgamation/config.h
@@ -0,0 +1,32 @@ +/* On Windows and OSX, SQLite uses preprocessor macros to configure itself. On + * Linux, it expects config.h from autoconf. autoconf generates config.h by + * compiling a series of probe programs, and Chromium's build system has no + * "configure" phase to put such generation in. This file is a workaround for + * this issue. + */ +/* TODO(shess): Expand this to OSX and Windows? */ +/* TODO(shess): Consider config_linux.h, config_mac.h, config_win.h? */ + +/* NOTE(shess): This file is included by sqlite3.c, be very careful about adding + * #include lines. + */ +/* TODO(shess): Consider using build/build_config.h for OS_ macros. */ +/* TODO(shess): build_config.h uses unistd.h, perhaps for portability reasons, + * but AFAICT there are no current portability concerns here. limits.h is + * another alternative. + */ +#include <features.h> + +/* SQLite wants to track malloc sizes. On OSX it uses malloc_size(), on + * Windows _msize(), elsewhere it handles it manually by enlarging the malloc + * and injecting a field. Enable malloc_usable_size() for Linux. + * + * malloc_usable_size() is not exported by the Android NDK. It is not + * implemented by uclibc. + */ +#if defined(__linux__) && !defined(__UCLIBC__) +#define HAVE_MALLOC_H 1 +#define HAVE_MALLOC_USABLE_SIZE 1 +#endif + +/* TODO(shess): Eat other config options from gn and gyp? */
diff --git a/third_party/sqlite/sqlite.gyp b/third_party/sqlite/sqlite.gyp index e8ad210..d0357b7 100644 --- a/third_party/sqlite/sqlite.gyp +++ b/third_party/sqlite/sqlite.gyp
@@ -79,14 +79,11 @@ 'fdatasync=fdatasync', ], }], - # SQLite wants to track malloc sizes. On OSX it uses malloc_size(), on - # Windows _msize(), elsewhere it handles it manually by enlarging the - # malloc and injecting a field. Enable malloc_usable_size() for Linux. - # NOTE(shess): Android does _not_ export malloc_usable_size(). + # Pull in config.h on Linux. This allows use of preprocessor macros + # which are not available to the build config. ['OS == "linux"', { 'defines': [ - 'HAVE_MALLOC_H', - 'HAVE_MALLOC_USABLE_SIZE', + '_HAVE_SQLITE_CONFIG_H', ], }], ['use_system_sqlite', { @@ -136,6 +133,7 @@ 'product_name': 'chromium_sqlite3', 'type': '<(component)', 'sources': [ + 'amalgamation/config.h', 'amalgamation/sqlite3.h', 'amalgamation/sqlite3.c', ],
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 6cb14000..ad59c84 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -97,7 +97,7 @@ """Return the contents of the stamp file, or '' if it doesn't exist.""" try: with open(STAMP_FILE, 'r') as f: - return f.read() + return f.read().rstrip() except IOError: return '' @@ -108,6 +108,7 @@ os.makedirs(os.path.dirname(STAMP_FILE)) with open(STAMP_FILE, 'w') as f: f.write(s) + f.write('\n') def GetSvnRevision(svn_repo): @@ -281,7 +282,13 @@ if not args.force_local_build: cds_file = "clang-%s.tgz" % PACKAGE_VERSION - cds_full_url = CDS_URL + '/Win/' + cds_file + if sys.platform == 'win32': + cds_full_url = CDS_URL + '/Win/' + cds_file + elif sys.platform == 'darwin': + cds_full_url = CDS_URL + '/Mac/' + cds_file + else: + assert sys.platform.startswith('linux') + cds_full_url = CDS_URL + '/Linux_x64/' + cds_file # Check if there's a prebuilt binary and if so just fetch that. That's # faster, and goma relies on having matching binary hashes on client and
diff --git a/tools/copyright_scanner/copyright_scanner.py b/tools/copyright_scanner/copyright_scanner.py index fa705d24..04b6407 100644 --- a/tools/copyright_scanner/copyright_scanner.py +++ b/tools/copyright_scanner/copyright_scanner.py
@@ -69,6 +69,7 @@ # Swarming tools, doesn't exist in the snapshot path_join('tools', 'swarming_client'), # Ignore sysroots. + path_join('build', 'linux', 'debian_wheezy_amd64-sysroot'), path_join('build', 'linux', 'debian_wheezy_arm-sysroot'), path_join('build', 'linux', 'debian_wheezy_mips-sysroot'), path_join('build', 'linux', 'debian_wheezy_i386-sysroot'),
diff --git a/tools/copyright_scanner/third_party_files_whitelist.txt b/tools/copyright_scanner/third_party_files_whitelist.txt index a8eee6aed..a9017b67 100644 --- a/tools/copyright_scanner/third_party_files_whitelist.txt +++ b/tools/copyright_scanner/third_party_files_whitelist.txt
@@ -67,9 +67,6 @@ # Copyright Apple Inc, Nokia Corporation and Torch Mobile Inc; BSD license. # Moved from third_party/WebKit/. content/renderer/history_entry.cc -# Copyright Apple Inc; BSD license. Moved from third_party/WebKit/. -content/renderer/input/input_scroll_elasticity_controller.cc -content/renderer/input/input_scroll_elasticity_controller.h # Copyright Google Inc, no license. Not used on Android. google_update/google_update_idl.idl # Copyright WebM Project authors; BSD license. Copied and modified from @@ -171,6 +168,9 @@ ui/base/cocoa/tool_tip_base_view.mm # Copyright The Chromium Authors, Apple Inc; BSD license. Not used on Android. ui/base/dragdrop/os_exchange_data_provider_win.cc +# Copyright Apple Inc; BSD license. Moved from third_party/WebKit/. +ui/events/blink/input_scroll_elasticity_controller.cc +ui/events/blink/input_scroll_elasticity_controller.h # Copyright The Chromium Authors, Michael Emmel, Google Inc; BSD license. This # third-party code is taken from WebKit, the license for which we already pick # up from webkit/.
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index dd1c69d..e068813 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -31,6 +31,14 @@ 'dev_gyp_debug': ['gyp', 'debug', 'shared', 'full_symbols'], 'dev_gyp_release': ['gyp', 'release', 'shared'], 'embedded_gyp_debug_bot': ['embedded', 'gyp', 'debug_bot'], + + # This is the "deployment" config for the blimp builds. Currently + # we want them to be debug, non-optimized builds (and we don't need any + # chrome branding), so we don't use the "official" mixin. + # We need chromeos and ozone to eliminate any dependencies on X11. We + # dont need aura as it is implied by chromeos and ozone. + 'gn_blimp_debug': ['gn', 'chromeos', 'ozone', 'debug'], + 'gn_debug_bot': ['gn', 'debug_bot'], 'gn_debug_bot_minimal_symbols': ['gn', 'debug_bot_minimal_symbols'], 'gn_debug_bot_minimal_symbols_x86': ['gn', 'debug_bot_minimal_symbols', 'x86'], @@ -459,6 +467,7 @@ }, 'official.desktop': { 'precise64': 'gn_official', + 'blimp-engine': 'gn_blimp_debug', }, 'official.desktop.continuous': { 'precise64 trunk': 'gn_official',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 5a9a7e0..614da80b 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -2503,6 +2503,7 @@ <action name="Cryptohome.PKCS11InitFail"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> + <obsolete>Deprecated as of 11/2015.</obsolete> </action> <action name="CustomTabsCustomActionButtonClick"> @@ -8722,7 +8723,16 @@ <action name="Notifications.Persistent.Clicked"> <owner>peter@chromium.org</owner> <description> - Recorded when a persistent notification gets clicked on by the user. + Recorded when the main body of a persistent notification gets clicked on by + the user (does not include action buttons). + </description> +</action> + +<action name="Notifications.Persistent.ClickedActionButton"> + <owner>peter@chromium.org</owner> + <description> + Recorded when one of a persistent notification's action buttons gets clicked + on by the user. </description> </action>
diff --git a/tools/metrics/actions/extract_actions.py b/tools/metrics/actions/extract_actions.py index 042775e1..8009e52 100755 --- a/tools/metrics/actions/extract_actions.py +++ b/tools/metrics/actions/extract_actions.py
@@ -295,9 +295,6 @@ actions.add('Updater.ServerCertificateChanged') actions.add('Updater.ServerCertificateFailed') - # Actions sent by Chrome OS cryptohome. - actions.add('Cryptohome.PKCS11InitFail') - def AddExtensionActions(actions): """Add actions reported by extensions via chrome.metricsPrivate API.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 1b0350e..1c99555 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -14113,9 +14113,10 @@ <summary>Whether the GCM connection was made via a proxy or not.</summary> </histogram> -<histogram name="GCM.ConnectionDisconnectErrorCode" enum="NetErrorCodes"> +<histogram name="GCM.ConnectionDisconnectErrorCode" + enum="CombinedHttpResponseAndNetErrorCode"> <owner>zea@chromium.org</owner> - <summary>Net error results from GCM disconnect events.</summary> + <summary>URL response and error codes from GCM disconnect events.</summary> </histogram> <histogram name="GCM.ConnectionEndpoint" enum="GCMEndpoints"> @@ -14123,9 +14124,10 @@ <summary>Number of connections made to each specific MCS endpoint.</summary> </histogram> -<histogram name="GCM.ConnectionFailureErrorCode" enum="NetErrorCodes"> +<histogram name="GCM.ConnectionFailureErrorCode" + enum="CombinedHttpResponseAndNetErrorCode"> <owner>zea@chromium.org</owner> - <summary>Net error results from GCM connection attempts.</summary> + <summary>URL response and error codes from GCM connection attempts.</summary> </histogram> <histogram name="GCM.ConnectionLatency" units="milliseconds"> @@ -18235,7 +18237,7 @@ <histogram name="Media.EME.CdmFileIO.FileSizeKBOnError" units="KB"> <owner>xhwang@chromium.org</owner> <summary> - Size in KB of the last file sucessfully read by the CDM through CDM FileIO + Size in KB of the last file successfully read by the CDM through CDM FileIO before a specific error happens. This is reported only when the error happens, which should be rare. </summary> @@ -18244,8 +18246,8 @@ <histogram name="Media.EME.CdmFileIO.FileSizeKBOnFirstRead" units="KB"> <owner>xhwang@chromium.org</owner> <summary> - Size in KB of the first file sucessfully read by the CDM through CDM FileIO. - This is recorded once per CDM instance. + Size in KB of the first file successfully read by the CDM through CDM + FileIO. This is recorded once per CDM instance. </summary> </histogram> @@ -20129,6 +20131,12 @@ </summary> </histogram> +<histogram name="MemoryPurgeController.ReclaimedPartitionAllocInactiveTab" + units="KB"> + <owner>bashi@chromium.org</owner> + <summary>The amount of reclaimed memory after a tab became inactive.</summary> +</histogram> + <histogram name="MemoryWarning.EvictedTabTimeSinceActive" units="ms"> <owner>lliabraa@chromium.org</owner> <summary> @@ -29810,6 +29818,15 @@ </summary> </histogram> +<histogram name="Notifications.PersistentNotificationActionCount" + units="buttons"> + <owner>johnme@chromium.org</owner> + <summary> + The number of action buttons the developer provided for a persistent Web + Notification. Logged whenever showNotification is called. + </summary> +</histogram> + <histogram name="Notifications.PersistentNotificationDataDeleted" enum="BooleanSuccess"> <owner>peter@chromium.org</owner> @@ -41971,6 +41988,177 @@ </summary> </histogram> +<histogram name="Search.ContextualSearchBasePageProtocol" + enum="ContextualSearchBasePageProtocol"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The protocol of the base page, logged at the time that any Search Term + Resolution Response is recieved. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchDurationNonPrefetched" + units="milliseconds"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The time from opening the panel until the SERP is fully loaded. Applies only + to non-prefetched requests. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchDurationPrefetched" + units="milliseconds"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The time from opening the panel until the SERP is fully loaded. Applies only + to prefetched requests. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchDurationSeen" units="milliseconds"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The time from initiating to ending a contextual search, when results were + seen as part of the search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchDurationUnseen" units="milliseconds"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The time from initiating to ending a contextual search, when results were + not seen as part of the search and the search did not end with the beginning + of another contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchDurationUnseenChained" + units="milliseconds"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The time from initiating to ending a contextual search, when results were + not seen as part of the search and the search ended with the beginning of + another contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchEnterClosed" + enum="ContextualSearchEnterClosedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (previous state and reason) of the first entry into the closed + panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchEnterExpanded" + enum="ContextualSearchEnterExpandedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (previous state and reason) of the first entry into the expanded + panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchEnterMaximized" + enum="ContextualSearchEnterMaximizedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (previous state and reason) of the first entry into the + maximized panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchEnterPeeked" + enum="ContextualSearchEnterPeekedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (previous state and reason) of the first entry into the peeked + panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchExitClosed" + enum="ContextualSearchExitClosedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (destination state and reason) of the first exit out of the + closed panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchExitExpanded" + enum="ContextualSearchExitExpandedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (destination state and reason) of the first exit out of the + expanded panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchExitMaximized" + enum="ContextualSearchExitMaximizedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (destination state and reason) of the first exit out of the + maximized panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchExitPeeked" + enum="ContextualSearchExitPeekedStateChange"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The details (destination state and reason) of the first exit out of the + peeked panel state within a contextual search. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchFallbackSearchRequestStatus" + enum="ContextualSearchSearchRequestStatus"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The status of the Contextual Search fallback Search request. Implemented for + Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchFirstRunFlowOutcome" + enum="ContextualSearchPreferenceState"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The state of the Contextual Search Preference after the first run flow. + Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchFirstRunPanelSeen" + enum="ContextualSearchFirstRunPanelSeen"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether the first run flow's panel was seen as part of a contextual search. + Only logged when the user triggered the first run flow yet exited the search + still in the undecided preference state. Implemented for Android. + </summary> +</histogram> + <histogram name="Search.ContextualSearchIconSpriteAnimated" enum="ContextualSearchIconSpriteAnimated"> <owner>donnd@chromium.org</owner> @@ -41983,6 +42171,26 @@ </summary> </histogram> +<histogram name="Search.ContextualSearchLowPrioritySearchRequestStatus" + enum="ContextualSearchSearchRequestStatus"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The status of the Contextual Search low priority Search request. Implemented + for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchNormalPrioritySearchRequestStatus" + enum="ContextualSearchSearchRequestStatus"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The status of the Contextual Search normal priority Search request. + Implemented for Android. + </summary> +</histogram> + <histogram name="Search.ContextualSearchPeekPromoCount" units="count"> <owner>donnd@chromium.org</owner> <owner>pedrosimonetti@chromium.org</owner> @@ -42025,6 +42233,141 @@ </summary> </histogram> +<histogram name="Search.ContextualSearchPreferenceState" + enum="ContextualSearchPreferenceState"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The state of the Contextual Search Preference. Can be logged multiple times. + Used to determine the population size (user view). Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPreferenceStateChange" + enum="ContextualSearchPreferenceState"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The Contextual Search preference state after a modification from the + preference menu. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPrefetchSummary" + enum="ContextualSearchPrefetchSummary"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + A summary histogram for prefetch timings, indicating fully preloaded, etc. + Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPromoOpenCount" units="opens"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The total count of times that the bar with the promo has been opened. Once + the user decides, this counter is no longer updated. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPromoOutcomeByGesture" + enum="ContextualSearchOutcomeByGesture"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The outcome of the promo broken down by original triggering gesture. Logged + for each view of the promo. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPromoSeenByGesture" + enum="ContextualSearchSeenByGesture"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether the promo was seen, broken down by original triggering gesture. + Logged each time the promo was activated. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPromoTapsBeforeFirstOpen" units="taps"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The historic number of taps that showed a peeking bar with the opt-out promo + before the first time the user opened the panel. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPromoTapsForNeverOpened" units="taps"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The historic number of taps that showed a peeking bar with the opt-out promo + for users who have never opened the panel. This count may be limited by the + Finch config param promo_on_limited_taps. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchPromoTapsRemaining" units="taps"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The number of remaining taps that can trigger the promo for this user. + Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchResolvedTermWords" + enum="ContextualSearchResolvedTermWords"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether the search term was single or multi-word, logged at the time that + any Search Term Resolution Response is recieved. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchResultsSeen" + enum="ContextualSearchResultsSeen"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether search results were seen as part of a contextual search. Implemented + for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchResultsSeenByGesture" + enum="ContextualSearchSeenByGesture"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether search results were seen, broken down by original triggering + gesture. Only includes users that have enabled. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchSelectionValid" + enum="ContextualSearchSelectionValid"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether a Contextual Search selection was valid. Implemented for Android. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchSerpLoadedOnClose" + enum="ContextualSearchLoaded"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + Whether the SERP was fully loaded when an opened panel was closed. + </summary> +</histogram> + <histogram name="Search.ContextualSearchShouldTranslate" enum="ContextualSearchShouldTranslate"> <owner>donnd@chromium.org</owner> @@ -42036,6 +42379,33 @@ </summary> </histogram> +<histogram name="Search.ContextualSearchTapsSinceOpenDecided" units="taps"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The count of taps that showed a peeking bar without the opt-out promo since + this user has last opened the panel. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchTapsSinceOpenUndecided" units="taps"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The count of taps that showed a peeking bar with the opt-out promo since + this user has last opened the panel. + </summary> +</histogram> + +<histogram name="Search.ContextualSearchTimeToSearch" units="milliseconds"> + <owner>donnd@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <summary> + The time between tapping on a word and performing a search. Implemented for + Android. + </summary> +</histogram> + <histogram name="Search.DefaultSearchChangeOrigin" enum="DefaultSearchChangeOrigin"> <owner>mathp@chromium.org</owner> @@ -47871,6 +48241,15 @@ </summary> </histogram> +<histogram name="Sync.URLFetchResponse" + enum="CombinedHttpResponseAndNetErrorCode"> + <owner>zea@chromium.org</owner> + <summary> + Counts of responses (both http code and net error code) for Sync URL + fetches. + </summary> +</histogram> + <histogram name="Sync.URLFetchTime" units="milliseconds"> <owner>zea@chromium.org</owner> <summary> @@ -48120,23 +48499,6 @@ </summary> </histogram> -<histogram name="Tab.RendererDetailedExitStatus" - enum="TabRendererDetailedExitStatus"> - <owner>wnwen@chromium.org</owner> - <summary> - Breakdown of renderer exit status. An extension of the counts in - Tab.RendererExitStatus. Only recorded on Android. - </summary> -</histogram> - -<histogram name="Tab.RendererExitStatus" enum="TabRendererExitStatus"> - <owner>wnwen@chromium.org</owner> - <summary> - The status of a renderer when the browser notices that the process has - exited. Only recorded on Android. - </summary> -</histogram> - <histogram name="Tab.RestoreResult" enum="TabRestoreResult"> <owner>lliabraa@chromium.org</owner> <summary> @@ -52878,6 +53240,24 @@ </summary> </histogram> +<histogram name="WebRTC.Call.EstimatedSendBitrateInKbps" units="kbits/s"> + <owner>holmer@chromium.org</owner> + <summary> + Average estimated send bitrate during a call, counted from first packet sent + until Call instance is destroyed. Only mesured for calls that are at least + 10 seconds long. + </summary> +</histogram> + +<histogram name="WebRTC.Call.PacerBitrateInKbps" units="kbits/s"> + <owner>holmer@chromium.org</owner> + <summary> + Average pacer bitrate during a call, counted from first packet sent until + Call instance is destroyed. Only mesured for calls that are at least 10 + seconds long. + </summary> +</histogram> + <histogram name="WebRTC.Call.RtcpBitrateReceivedInBps" units="bits/s"> <owner>holmer@chromium.org</owner> <summary> @@ -56769,6 +57149,106 @@ <int value="5" label="Pdf"/> </enum> +<enum name="ContextualSearchBasePageProtocol" type="int"> + <int value="0" label="Is HTTP"/> + <int value="1" label="Not HTTP"/> +</enum> + +<enum name="ContextualSearchEnterClosedStateChange" type="int"> + <int value="0" label="From Other"/> + <int value="1" label="From Peeked (back press)"/> + <int value="2" label="From Peeked (base page scroll)"/> + <int value="3" label="From Peeked (text select tap)"/> + <int value="4" label="From Expanded (back press)"/> + <int value="5" label="From Expanded (base page tap)"/> + <int value="6" label="From Expanded (fling)"/> + <int value="7" label="From Maximized (back press)"/> + <int value="8" label="From Maximized (fling)"/> + <int value="9" label="From Maximized (tab promotion)"/> + <int value="10" label="From Maximized (SERP navigation)"/> +</enum> + +<enum name="ContextualSearchEnterExpandedStateChange" type="int"> + <int value="0" label="From Other"/> + <int value="1" label="From Peeked (search bar tap)"/> + <int value="2" label="From Peeked (swipe)"/> + <int value="3" label="From Peeked (fling)"/> + <int value="4" label="From Maximized (swipe)"/> + <int value="5" label="From Maximized (fling)"/> +</enum> + +<enum name="ContextualSearchEnterMaximizedStateChange" type="int"> + <int value="0" label="Other"/> + <int value="1" label="From Peeked (swipe)"/> + <int value="2" label="From Peeked (fling)"/> + <int value="3" label="From Expanded (swipe)"/> + <int value="4" label="From Expanded (fling)"/> + <int value="5" label="From Expanded (SERP navigation)"/> +</enum> + +<enum name="ContextualSearchEnterPeekedStateChange" type="int"> + <int value="0" label="From Other"/> + <int value="1" label="From Closed (text select tap)"/> + <int value="2" label="From Closed (text select long press)"/> + <int value="3" label="From Peeked (text select tap)"/> + <int value="4" label="From Peeked (text select long press)"/> + <int value="5" label="From Expanded (search bar tap)"/> + <int value="6" label="From Expanded (swipe)"/> + <int value="7" label="From Expanded (fling)"/> + <int value="8" label="From Maximized (swipe)"/> + <int value="9" label="From Maximized (fling)"/> +</enum> + +<enum name="ContextualSearchExitClosedStateChange" type="int"> + <int value="0" label="Other"/> + <int value="1" label="Peek (text select tap)"/> + <int value="2" label="Peek (text select long press)"/> +</enum> + +<enum name="ContextualSearchExitExpandedStateChange" type="int"> + <int value="0" label="Other"/> + <int value="1" label="Close (back press)"/> + <int value="2" label="Close (base page tap)"/> + <int value="3" label="Close (fling)"/> + <int value="4" label="Peek (search bar tap)"/> + <int value="5" label="Peek (swipe)"/> + <int value="6" label="Peek (fling)"/> + <int value="7" label="Maximize (swipe)"/> + <int value="8" label="Maximize (fling)"/> + <int value="9" label="Maximize (SERP navigation)"/> +</enum> + +<enum name="ContextualSearchExitMaximizedStateChange" type="int"> + <int value="0" label="Other"/> + <int value="1" label="Close (back press)"/> + <int value="2" label="Close (fling)"/> + <int value="3" label="Close (tab promotion)"/> + <int value="4" label="Close (SERP navigation)"/> + <int value="5" label="Peek (swipe)"/> + <int value="6" label="Peek (fling)"/> + <int value="7" label="Expand (swipe)"/> + <int value="8" label="Expand (fling)"/> +</enum> + +<enum name="ContextualSearchExitPeekedStateChange" type="int"> + <int value="0" label="Other"/> + <int value="1" label="Close (back press)"/> + <int value="2" label="Close (base page scroll)"/> + <int value="3" label="Close (text select tap)"/> + <int value="4" label="Peek (text select tap)"/> + <int value="5" label="Peek (text select long press)"/> + <int value="6" label="Expand (search bar tap)"/> + <int value="7" label="Expand (swipe)"/> + <int value="8" label="Expand (fling)"/> + <int value="9" label="Maximize (swipe)"/> + <int value="10" label="To Maximize (fling)"/> +</enum> + +<enum name="ContextualSearchFirstRunPanelSeen" type="int"> + <int value="0" label="Seen"/> + <int value="1" label="Unseen"/> +</enum> + <enum name="ContextualSearchIconSpriteAnimated" type="int"> <int value="0" label="Animated, seen, from tap"/> <int value="1" label="Animated, not seen, from tap"/> @@ -56780,6 +57260,20 @@ <int value="7" label="Not animated, not seen, from long press"/> </enum> +<enum name="ContextualSearchLoaded" type="int"> + <int value="0" label="Partially Loaded"/> + <int value="1" label="Fully Loaded"/> +</enum> + +<enum name="ContextualSearchOutcomeByGesture" type="int"> + <int value="0" label="Enabled, from Tap"/> + <int value="1" label="Disabled, from Tap"/> + <int value="2" label="Undecided from Tap"/> + <int value="3" label="Enabled, from Long-press"/> + <int value="4" label="Disabled, from Long-press"/> + <int value="5" label="Undecided from Long-press"/> +</enum> + <enum name="ContextualSearchPeekPromoOutcome" type="int"> <summary>The outcome of the Contextual Search Peek Promo.</summary> <int value="0" label="Peek Promo was seen, Panel was opened"/> @@ -56788,6 +57282,45 @@ <int value="3" label="Peek Promo was not seen, Panel was not opened"/> </enum> +<enum name="ContextualSearchPreferenceState" type="int"> + <int value="0" label="Uninitialized"/> + <int value="1" label="Enabled"/> + <int value="2" label="Disabled"/> +</enum> + +<enum name="ContextualSearchPrefetchSummary" type="int"> + <int value="0" label="Prefetched, partly loaded"/> + <int value="1" label="Fully preloaded"/> + <int value="2" label="Not prefetched"/> +</enum> + +<enum name="ContextualSearchResolvedTermWords" type="int"> + <int value="0" label="Single Word"/> + <int value="1" label="Multi Word"/> +</enum> + +<enum name="ContextualSearchResultsSeen" type="int"> + <int value="0" label="Seen"/> + <int value="1" label="Unseen"/> +</enum> + +<enum name="ContextualSearchSearchRequestStatus" type="int"> + <int value="0" label="Not Failed"/> + <int value="1" label="Failed"/> +</enum> + +<enum name="ContextualSearchSeenByGesture" type="int"> + <int value="0" label="Seen, from Tap"/> + <int value="1" label="Not seen, from Tap"/> + <int value="2" label="Seen, from Long-press"/> + <int value="3" label="Not seen, from Long-press"/> +</enum> + +<enum name="ContextualSearchSelectionValid" type="int"> + <int value="0" label="Valid"/> + <int value="1" label="Invalid"/> +</enum> + <enum name="ContextualSearchShouldTranslate" type="int"> <summary> Notes when a translation one-box should be forced by Contextual Search. @@ -62721,6 +63254,12 @@ <int value="1022" label="CSSFilterContrast"/> <int value="1023" label="CSSFilterBlur"/> <int value="1024" label="CSSFilterDropShadow"/> + <int value="1025" label="BackgroundSyncRegister"/> + <int value="1026" label="BorderImageWithBorderStyleNone"/> + <int value="1027" label="ExecCommandOnInputOrTextarea"/> + <int value="1028" label="V8History_ScrollRestoration_AttributeGetter"/> + <int value="1029" label="V8History_ScrollRestoration_AttributeSetter"/> + <int value="1030" label="SVG1DOMFilter"/> </enum> <enum name="FetchRequestMode" type="int"> @@ -68888,9 +69427,10 @@ <int value="15" label="Show Cached Page button shown"/> <int value="16" label="Show Cached Page button clicked"/> <int value="17" label="Diagnose button clicked"/> - <int value="18" label="Show Saved Pages Button Shown"/> - <int value="19" label="Show Saved Pages Button Clicked"/> - <int value="20" label="Show Saved Pages Button Click Load Error"/> + <int value="18" label="Show Offline Pages Button Shown"/> + <int value="19" label="Show Offline Pages Button Clicked"/> + <int value="20" label="Show Offline Copy Button Shown"/> + <int value="21" label="Show Offline Copy Button Clicked"/> </enum> <enum name="NetInternalsUiFeature" type="int"> @@ -76150,24 +76690,6 @@ <int value="2" label="Hidden in background app"/> </enum> -<enum name="TabRendererDetailedExitStatus" type="int"> - <int value="0" label="Empty minidump in running app"/> - <int value="1" label="Empty minidump in paused app"/> - <int value="2" label="Empty minidump in background app"/> - <int value="3" label="Valid minidump in running app"/> - <int value="4" label="Valid minidump in paused app"/> - <int value="5" label="Valid minidump in background app"/> -</enum> - -<enum name="TabRendererExitStatus" type="int"> - <int value="0" label="OOM protected in running app"/> - <int value="1" label="OOM protected in paused app"/> - <int value="2" label="OOM protected in background app"/> - <int value="3" label="Not protected in running app"/> - <int value="4" label="Not protected in paused app"/> - <int value="5" label="Not protected in background app"/> -</enum> - <enum name="TabRestoreResult" type="int"> <int value="0" label="Failure (other)"/> <int value="1" label="Success"/> @@ -78262,6 +78784,15 @@ <affected-histogram name="ChromeOS.MachineIdRegen.AgeSeconds"/> </histogram_suffixes> +<histogram_suffixes name="ClockResolution" separator="."> + <suffix name="HighResolutionClock" + label="base::TimeTicks::IsHighResolution() is true for this measurement"/> + <suffix name="LowResolutionClock" + label="base::TimeTicks::IsHighResolution() is false for this + measurement"/> + <affected-histogram name="PageLoad.Timing2.NavigationToFirstContentfulPaint"/> +</histogram_suffixes> + <histogram_suffixes name="CloudPrintRequests" separator="."> <suffix name="Register" label="Register request"/> <suffix name="UpdatePrinter" label="Update printer request"/>
diff --git a/tools/perf/benchmarks/tab_switching.py b/tools/perf/benchmarks/tab_switching.py index 37eed56..6faf439 100644 --- a/tools/perf/benchmarks/tab_switching.py +++ b/tools/perf/benchmarks/tab_switching.py
@@ -103,28 +103,3 @@ @classmethod def Name(cls): return 'tab_switching.tough_image_cases' - - -@benchmark.Disabled('all') -class TabSwitchingFlashEnergyCases(perf_benchmark.PerfBenchmark): - test = tab_switching.TabSwitching - page_set = page_sets.FlashEnergyCasesPageSet - options = {'pageset_repeat': 10} - - @classmethod - def Name(cls): - return 'tab_switching.flash_energy_cases' - - -@benchmark.Disabled('all') -class TabSwitchingPluginPowerSaver(perf_benchmark.PerfBenchmark): - test = tab_switching.TabSwitching - page_set = page_sets.FlashEnergyCasesPageSet - options = {'pageset_repeat': 10} - - def SetExtraBrowserOptions(self, options): - options.AppendExtraBrowserArgs(['--enable-plugin-power-saver']) - - @classmethod - def Name(cls): - return 'tab_switching.plugin_power_saver'
diff --git a/tools/telemetry/telemetry/internal/util/bootstrap.py b/tools/perf/core/bootstrap.py similarity index 98% rename from tools/telemetry/telemetry/internal/util/bootstrap.py rename to tools/perf/core/bootstrap.py index ba8a1494..3a25f5f 100644 --- a/tools/telemetry/telemetry/internal/util/bootstrap.py +++ b/tools/perf/core/bootstrap.py
@@ -25,6 +25,7 @@ davclient = None +# TODO(eakuefner): Switch this link to tools/perf version after verifying. # Link to file containing the 'davclient' WebDAV client library. _DAVCLIENT_URL = ('https://src.chromium.org/chrome/trunk/src/tools/' 'telemetry/third_party/davclient/davclient.py')
diff --git a/tools/telemetry/telemetry/internal/util/find_dependencies.py b/tools/perf/core/find_dependencies.py similarity index 93% rename from tools/telemetry/telemetry/internal/util/find_dependencies.py rename to tools/perf/core/find_dependencies.py index bb0673f9..5d73816 100644 --- a/tools/telemetry/telemetry/internal/util/find_dependencies.py +++ b/tools/perf/core/find_dependencies.py
@@ -12,13 +12,14 @@ from telemetry import benchmark from telemetry.core import discover -from telemetry.internal.util import bootstrap from telemetry.internal.util import command_line from telemetry.internal.util import path from telemetry.internal.util import path_set -from modulegraph import modulegraph +from modulegraph import modulegraph # pylint: disable=import-error +from core import bootstrap +from core import path_util DEPS_FILE = 'bootstrap_deps' @@ -29,7 +30,7 @@ return [] deps_paths = bootstrap.ListAllDepsPaths(deps_file) return set(os.path.realpath(os.path.join( - path.GetChromiumSrcDir(), '..', deps_path)) + path_util.GetChromiumSrcDir(), '..', deps_path)) for deps_path in deps_paths) @@ -64,7 +65,7 @@ # This check is done after the logging/printing above to make sure that # we also print out the dependency edges that include python packages # that are not in chromium. - if not path.IsSubpath(module_path, path.GetChromiumSrcDir()): + if not path.IsSubpath(module_path, path_util.GetChromiumSrcDir()): continue yield module_path @@ -149,9 +150,10 @@ # and all its dependencies. If the user doesn't pass any arguments, we just # have Telemetry. dependencies |= FindPythonDependencies(os.path.realpath( - os.path.join(path.GetTelemetryDir(), 'telemetry', 'benchmark_runner.py'))) + os.path.join(path_util.GetTelemetryDir(), + 'telemetry', 'benchmark_runner.py'))) dependencies |= FindPythonDependencies(os.path.realpath( - os.path.join(path.GetTelemetryDir(), + os.path.join(path_util.GetTelemetryDir(), 'telemetry', 'testing', 'run_tests.py'))) # Add dependencies. @@ -171,7 +173,7 @@ def ZipDependencies(target_paths, dependencies, options): - base_dir = os.path.dirname(os.path.realpath(path.GetChromiumSrcDir())) + base_dir = os.path.dirname(os.path.realpath(path_util.GetChromiumSrcDir())) with zipfile.ZipFile(options.zip, 'w', zipfile.ZIP_DEFLATED) as zip_file: # Add dependencies to archive.
diff --git a/tools/telemetry/telemetry/internal/util/find_dependencies_unittest.py b/tools/perf/core/find_dependencies_unittest.py similarity index 96% rename from tools/telemetry/telemetry/internal/util/find_dependencies_unittest.py rename to tools/perf/core/find_dependencies_unittest.py index 7d43915..43d680e0 100644 --- a/tools/telemetry/telemetry/internal/util/find_dependencies_unittest.py +++ b/tools/perf/core/find_dependencies_unittest.py
@@ -6,7 +6,8 @@ import unittest from telemetry.core import util -from telemetry.internal.util import find_dependencies + +from core import find_dependencies class FindDependenciesTest(unittest.TestCase):
diff --git a/tools/telemetry/telemetry/telemetry_dependencies_unittest.py b/tools/perf/core/telemetry_dependencies_unittest.py similarity index 70% rename from tools/telemetry/telemetry/telemetry_dependencies_unittest.py rename to tools/perf/core/telemetry_dependencies_unittest.py index b61684e..20c0775 100644 --- a/tools/telemetry/telemetry/telemetry_dependencies_unittest.py +++ b/tools/perf/core/telemetry_dependencies_unittest.py
@@ -2,18 +2,22 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import json +# TODO(eakuefner): Remove this test once Telemetry lives in Catapult. import os import platform import sys import unittest -from telemetry.internal.util import find_dependencies from telemetry.internal.util import path +from core import find_dependencies +from core import path_util -_TELEMETRY_DEPS_PATH = os.path.join( - path.GetTelemetryDir(), 'telemetry', 'TELEMETRY_DEPS') +_TELEMETRY_DEPS = [ + 'build/android/devil/', + 'build/android/pylib/', + 'third_party/catapult/', + 'tools/telemetry/'] def _GetCurrentTelemetryDependencies(): @@ -25,20 +29,13 @@ def _GetRestrictedTelemetryDeps(): - with open(_TELEMETRY_DEPS_PATH, 'r') as f: - telemetry_deps = json.load(f) - # Normalize paths in telemetry_deps since TELEMETRY_DEPS file only contain # the relative path in chromium/src/. def NormalizePath(p): p = p.replace('/', os.path.sep) - return os.path.realpath(os.path.join(path.GetChromiumSrcDir(), p)) + return os.path.realpath(os.path.join(path_util.GetChromiumSrcDir(), p)) - telemetry_deps['file_deps'] = [ - NormalizePath(p) for p in telemetry_deps['file_deps']] - telemetry_deps['directory_deps'] = [ - NormalizePath(p) for p in telemetry_deps['directory_deps']] - return telemetry_deps + return map(NormalizePath, _TELEMETRY_DEPS) class TelemetryDependenciesTest(unittest.TestCase): @@ -48,9 +45,7 @@ current_dependencies = _GetCurrentTelemetryDependencies() extra_dep_paths = [] for dep_path in current_dependencies: - if not (dep_path in telemetry_deps['file_deps'] or - any(path.IsSubpath(dep_path, d) - for d in telemetry_deps['directory_deps'])): + if not any(path.IsSubpath(dep_path, d) for d in telemetry_deps): extra_dep_paths.append(dep_path) # Temporarily ignore failure on Mac because test is failing on Mac 10.8 bot. # crbug.com/522335
diff --git a/tools/perf/find_dependencies b/tools/perf/find_dependencies index 2d0691a88..ec824a2 100755 --- a/tools/perf/find_dependencies +++ b/tools/perf/find_dependencies
@@ -5,10 +5,7 @@ import sys -from core import path_util -sys.path.append(path_util.GetTelemetryDir()) - -from telemetry.internal.util import find_dependencies +from core import find_dependencies if __name__ == '__main__':
diff --git a/tools/perf/measurements/startup.py b/tools/perf/measurements/startup.py index 6acf9d2c..e1cbc3ac 100644 --- a/tools/perf/measurements/startup.py +++ b/tools/perf/measurements/startup.py
@@ -29,10 +29,6 @@ ]) keychain_metric.KeychainMetric.CustomizeBrowserOptions(options) - def RunNavigateSteps(self, page, tab): - # Overriden so that no page navigation occurs - startup to the NTP. - pass - def ValidateAndMeasurePage(self, page, tab, results): keychain_metric.KeychainMetric().AddResults(tab, results) startup_metric.StartupMetric().AddResults(tab, results)
diff --git a/tools/perf/page_sets/blank_page.py b/tools/perf/page_sets/blank_page.py index 6f87074..fb2ac71 100644 --- a/tools/perf/page_sets/blank_page.py +++ b/tools/perf/page_sets/blank_page.py
@@ -9,6 +9,18 @@ def __init__(self, url, page_set): super(BlankPage, self).__init__(url, page_set=page_set) + def RunPageInteractions(self, action_runner): + # Request a RAF and wait for it to be processed to ensure that the metric + # Startup.FirstWebContents.NonEmptyPaint2 is recorded. + action_runner.ExecuteJavaScript( + """ + this.hasRunRAF = 0; + requestAnimationFrame(function() { + this.hasRunRAF = 1; + }); + """ + ) + action_runner.WaitForJavaScriptCondition("this.hasRunRAF == 1") class BlankPageSet(story.StorySet): """A single blank page."""
diff --git a/tools/perf/page_sets/data/flash_energy_cases.json b/tools/perf/page_sets/data/flash_energy_cases.json deleted file mode 100644 index cb8f10e..0000000 --- a/tools/perf/page_sets/data/flash_energy_cases.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "description": "Describes the Web Page Replay archives for a page set. Don't edit by hand! Use record_wpr for updating.", - "archives": { - "flash_energy_cases_000.wpr": [ - "http://nos.nl/video/712855-eerste-beelden-na-de-aanslag-in-canada.html", - "http://forum.gazeta.pl/forum/f,17007,Polityka_i_Gospodarka.html", - "http://tinypic.com/", - "https://www.facebook.com/video.php?v=524346051035153&set=vb.134474600022302&type=2&theater", - "http://v.qq.com/cover/d/dm9vn9cnsn2v2gx.html?ptag=v.newplaybutton.program.dpjd", - "http://videos.huffingtonpost.com/politics/protesters-march-to-hong-kong-leaders-home-518476075" - ] - } -} \ No newline at end of file
diff --git a/tools/perf/page_sets/data/flash_energy_cases_000.wpr.sha1 b/tools/perf/page_sets/data/flash_energy_cases_000.wpr.sha1 deleted file mode 100644 index ee693cf..0000000 --- a/tools/perf/page_sets/data/flash_energy_cases_000.wpr.sha1 +++ /dev/null
@@ -1 +0,0 @@ -7d928f2c2f95999e26f00c72f8c9dd9a55932643 \ No newline at end of file
diff --git a/tools/perf/page_sets/flash_energy_cases.py b/tools/perf/page_sets/flash_energy_cases.py deleted file mode 100644 index 6b512988..0000000 --- a/tools/perf/page_sets/flash_energy_cases.py +++ /dev/null
@@ -1,40 +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. -from telemetry.page import page as page_module -from telemetry.page import shared_page_state -from telemetry import story - - -class FlashEnergyCasesPage(page_module.Page): - - def __init__(self, url, page_set): - super(FlashEnergyCasesPage, self).__init__( - url=url, page_set=page_set, - shared_page_state_class=shared_page_state.SharedDesktopPageState) - self.archive_data_file = 'data/flash_energy_cases.json' - - -class FlashEnergyCasesPageSet(story.StorySet): - - """ Pages with flash heavy content. """ - - def __init__(self): - super(FlashEnergyCasesPageSet, self).__init__( - archive_data_file='data/flash_energy_cases.json', - cloud_storage_bucket=story.PARTNER_BUCKET) - - urls_list = [ - # pylint: disable=line-too-long - 'http://v.qq.com/cover/d/dm9vn9cnsn2v2gx.html?ptag=v.newplaybutton.program.dpjd', - 'http://videos.huffingtonpost.com/politics/protesters-march-to-hong-kong-leaders-home-518476075', - 'http://nos.nl/video/712855-eerste-beelden-na-de-aanslag-in-canada.html', - # Why: Large flash ad - 'http://forum.gazeta.pl/forum/f,17007,Polityka_i_Gospodarka.html', - # Why: Multiple flash ads - 'http://tinypic.com/', - 'https://www.facebook.com/video.php?v=524346051035153&set=vb.134474600022302&type=2&theater' - ] - - for url in urls_list: - self.AddStory(FlashEnergyCasesPage(url, self))
diff --git a/tools/perf/page_sets/infinite_scroll_cases.py b/tools/perf/page_sets/infinite_scroll_cases.py index 4781d25..993e555 100644 --- a/tools/perf/page_sets/infinite_scroll_cases.py +++ b/tools/perf/page_sets/infinite_scroll_cases.py
@@ -13,14 +13,15 @@ window.Worker = undefined; window.performance = undefined;''' -def _ScrollAction(action_runner, scroll_amount): +def _ScrollAction(action_runner, scroll_amount, delay, repeat): action_runner.Wait(TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS) with action_runner.CreateInteraction('Begin'): action_runner.tab.browser.DumpMemory() with action_runner.CreateInteraction('Scrolling'): action_runner.RepeatableBrowserDrivenScroll( y_scroll_distance_ratio=scroll_amount, - repeat_count=0) + repeat_delay_ms=delay, + repeat_count=repeat) with action_runner.CreateInteraction('End'): action_runner.tab.browser.DumpMemory() @@ -34,11 +35,12 @@ class DerivedSmoothPage(base_page_cls): # pylint: disable=no-init def RunPageInteractions(self, action_runner): _WaitAction(action_runner) - _ScrollAction(action_runner, self.scroll_amount) + _ScrollAction(action_runner, self.scroll_amount, self.delay, self.repeat) return DerivedSmoothPage class InfiniteScrollPage(page_module.Page): - def __init__(self, url, page_set, name, scroll_amount, credentials=None): + def __init__(self, url, page_set, name, scroll_amount, delay, repeat, + credentials=None): super(InfiniteScrollPage, self).__init__( url=url, page_set=page_set, name=name, shared_page_state_class=shared_page_state.SharedPageState, @@ -46,6 +48,8 @@ self.credentials = credentials self.script_to_evaluate_on_commit = STARTUP_SCRIPT self.scroll_amount = scroll_amount + self.delay = delay + self.repeat = repeat class InfiniteScrollPageSet(story.StorySet): """ Top pages that can be scrolled for many pages. """ @@ -57,14 +61,15 @@ # continiously throught the test without hitting the end of the page. SCROLL_FAR = 30 SCROLL_NEAR = 13 + SCROLL_PAGE = 1 pages = [ - ('https://www.facebook.com/shakira', 'facebook', SCROLL_FAR), - ('https://twitter.com/taylorswift13', 'twitter', SCROLL_FAR), - ('http://espn.go.com/', 'espn', SCROLL_NEAR), - ('https://www.yahoo.com', 'yahoo', SCROLL_NEAR), - ('http://techcrunch.tumblr.com/', 'tumblr', SCROLL_FAR), - ('https://www.flickr.com/explore', 'flickr', SCROLL_FAR) + ('https://www.facebook.com/shakira', 'facebook', SCROLL_FAR, 0, 0), + ('https://twitter.com/taylorswift13', 'twitter', SCROLL_PAGE, 10, 30), + ('http://espn.go.com/', 'espn', SCROLL_NEAR, 0, 0), + ('https://www.yahoo.com', 'yahoo', SCROLL_NEAR, 0, 0), + ('http://techcrunch.tumblr.com/', 'tumblr', SCROLL_FAR, 0, 0), + ('https://www.flickr.com/explore', 'flickr', SCROLL_FAR, 0, 0) ] - for (url, name, scroll_amount) in pages: + for (url, name, scroll_amount, delay, repeat) in pages: page_class = _CreateInfiniteScrollPageClass(InfiniteScrollPage) - self.AddStory(page_class(url, self, name, scroll_amount)) + self.AddStory(page_class(url, self, name, scroll_amount, delay, repeat))
diff --git a/tools/perf/third_party/__init__.py b/tools/perf/third_party/__init__.py new file mode 100644 index 0000000..50b23df --- /dev/null +++ b/tools/perf/third_party/__init__.py
@@ -0,0 +1,3 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file.
diff --git a/tools/telemetry/third_party/davclient/README.chromium b/tools/perf/third_party/davclient/README.chromium similarity index 100% rename from tools/telemetry/third_party/davclient/README.chromium rename to tools/perf/third_party/davclient/README.chromium
diff --git a/tools/telemetry/third_party/davclient/davclient.py b/tools/perf/third_party/davclient/davclient.py similarity index 100% rename from tools/telemetry/third_party/davclient/davclient.py rename to tools/perf/third_party/davclient/davclient.py
diff --git a/tools/telemetry/find_dependencies b/tools/telemetry/find_dependencies deleted file mode 100755 index c8ec251..0000000 --- a/tools/telemetry/find_dependencies +++ /dev/null
@@ -1,16 +0,0 @@ -#!/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. - -from telemetry import decorators -from telemetry.internal.util import find_dependencies - - -@decorators.Deprecated(2015, 11, 23, 'Please use tools/perf/find_dependencies.') -def main(): - find_dependencies.FindDependenciesCommand.main() - - -if __name__ == '__main__': - main()
diff --git a/tools/telemetry/telemetry/TELEMETRY_DEPS b/tools/telemetry/telemetry/TELEMETRY_DEPS deleted file mode 100644 index 7b6030c..0000000 --- a/tools/telemetry/telemetry/TELEMETRY_DEPS +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "NOTE": [ - "Please do NOT add new dependencies into this file. Contact ", - "aiolos@, dtu@, or nednguyen@ on how to proceed with your change." - ], - "directory_deps": [ - "build/android/devil/", - "build/android/pylib/", - "third_party/catapult/", - "tools/telemetry/" - ], - "file_deps": [ - ] -}
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt index 212b9ed9..3023acf 100644 --- a/tools/valgrind/drmemory/suppressions_full.txt +++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1819,11 +1819,6 @@ *!ash::test::ShelfViewTest_OverflowBubbleSize_Test::TestBody *!testing::internal::HandleExceptionsInMethodIfSupported<> -UNADDRESSABLE ACCESS -name=bug_442969 -*!testing::internal::CmpHelperNE<> -*!extensions::WebrtcAudioPrivateTest_GetAndSetWithMediaStream_Test::RunTestOnMainThread - UNINITIALIZED READ name=bug_455417 *!std::char_traits<>::compare
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc index 2743755d..92f0ef0 100644 --- a/ui/base/clipboard/clipboard_win.cc +++ b/ui/base/clipboard/clipboard_win.cc
@@ -160,10 +160,10 @@ return data; } -bool BitmapHasInvalidPremultipliedColors(const SkBitmap& bitmap) { - for (int x = 0; x < bitmap.width(); ++x) { - for (int y = 0; y < bitmap.height(); ++y) { - uint32_t pixel = *bitmap.getAddr32(x, y); +bool BitmapHasInvalidPremultipliedColors(const SkPixmap& pixmap) { + for (int x = 0; x < pixmap.width(); ++x) { + for (int y = 0; y < pixmap.height(); ++y) { + uint32_t pixel = *pixmap.addr32(x, y); if (SkColorGetR(pixel) > SkColorGetA(pixel) || SkColorGetG(pixel) > SkColorGetA(pixel) || SkColorGetB(pixel) > SkColorGetA(pixel)) @@ -173,10 +173,10 @@ return false; } -void MakeBitmapOpaque(const SkBitmap& bitmap) { - for (int x = 0; x < bitmap.width(); ++x) { - for (int y = 0; y < bitmap.height(); ++y) { - *bitmap.getAddr32(x, y) = SkColorSetA(*bitmap.getAddr32(x, y), 0xFF); +void MakeBitmapOpaque(SkPixmap* pixmap) { + for (int x = 0; x < pixmap->width(); ++x) { + for (int y = 0; y < pixmap->height(); ++y) { + *pixmap->writable_addr32(x, y) = SkColorSetA(*pixmap->addr32(x, y), 0xFF); } } } @@ -631,14 +631,13 @@ // we assume the alpha channel contains garbage and force the bitmap to be // opaque as well. Note that this heuristic will fail on a transparent bitmap // containing only black pixels... - const SkBitmap& device_bitmap = - canvas.sk_canvas()->getDevice()->accessBitmap(true); + SkPixmap device_pixels; + skia::GetWritablePixels(canvas.sk_canvas(), &device_pixels); { - SkAutoLockPixels lock(device_bitmap); bool has_invalid_alpha_channel = bitmap->bmiHeader.biBitCount < 32 || - BitmapHasInvalidPremultipliedColors(device_bitmap); + BitmapHasInvalidPremultipliedColors(device_pixels); if (has_invalid_alpha_channel) { - MakeBitmapOpaque(device_bitmap); + MakeBitmapOpaque(&device_pixels); } }
diff --git a/ui/base/resource/resource_bundle_mac_unittest.mm b/ui/base/resource/resource_bundle_mac_unittest.mm index 9a580b2..9b43bec 100644 --- a/ui/base/resource/resource_bundle_mac_unittest.mm +++ b/ui/base/resource/resource_bundle_mac_unittest.mm
@@ -4,7 +4,7 @@ #include "ui/base/resource/resource_bundle.h" -#import <Appkit/Appkit.h> +#import <AppKit/AppKit.h> #include "base/base_paths.h" #include "base/big_endian.h"
diff --git a/ui/chromeos/BUILD.gn b/ui/chromeos/BUILD.gn index 39412f1..69ebacb 100644 --- a/ui/chromeos/BUILD.gn +++ b/ui/chromeos/BUILD.gn
@@ -49,6 +49,7 @@ "//chromeos:chromeos", "//chromeos:power_manager_proto", "//components/device_event_log", + "//components/onc", "//skia", "//ui/aura", "//ui/base",
diff --git a/ui/chromeos/network/network_info.h b/ui/chromeos/network/network_info.h index 700e415..6ffe87d0 100644 --- a/ui/chromeos/network/network_info.h +++ b/ui/chromeos/network/network_info.h
@@ -26,6 +26,7 @@ std::string service_path; base::string16 label; + base::string16 tooltip; gfx::ImageSkia image; bool disable; bool highlight;
diff --git a/ui/chromeos/network/network_list.cc b/ui/chromeos/network/network_list.cc index 76cbaf6..0941205 100644 --- a/ui/chromeos/network/network_list.cc +++ b/ui/chromeos/network/network_list.cc
@@ -7,11 +7,14 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" #include "chromeos/dbus/power_manager_client.h" +#include "chromeos/login/login_state.h" +#include "chromeos/network/managed_network_configuration_handler.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_state_handler_observer.h" #include "components/device_event_log/device_event_log.h" #include "grit/ui_chromeos_strings.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/chromeos/network/network_icon.h" #include "ui/chromeos/network/network_icon_animation.h" @@ -21,12 +24,40 @@ #include "ui/views/controls/label.h" #include "ui/views/view.h" +using chromeos::LoginState; using chromeos::NetworkHandler; using chromeos::NetworkStateHandler; +using chromeos::ManagedNetworkConfigurationHandler; using chromeos::NetworkTypePattern; namespace ui { +namespace { + +bool IsProhibitedByPolicy(const chromeos::NetworkState* network) { + if (!NetworkTypePattern::WiFi().MatchesType(network->type())) + return false; + if (!LoginState::IsInitialized() || !LoginState::Get()->IsUserLoggedIn()) + return false; + ManagedNetworkConfigurationHandler* managed_configuration_handler = + NetworkHandler::Get()->managed_network_configuration_handler(); + const base::DictionaryValue* global_network_config = + managed_configuration_handler->GetGlobalConfigFromPolicy( + std::string() /* no username hash, device policy */); + bool policy_prohibites_unmanaged = false; + if (global_network_config) { + global_network_config->GetBooleanWithoutPathExpansion( + ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect, + &policy_prohibites_unmanaged); + } + if (!policy_prohibites_unmanaged) + return false; + return !managed_configuration_handler->FindPolicyByGuidAndProfile( + network->guid(), network->profile_path()); +} + +} // namespace + // NetworkListView: NetworkListView::NetworkListView(NetworkListDelegate* delegate) @@ -83,12 +114,14 @@ // First, update state for all networks bool animating = false; + for (size_t i = 0; i < network_list_.size(); ++i) { NetworkInfo* info = network_list_[i]; const chromeos::NetworkState* network = handler->GetNetworkState(info->service_path); if (!network) continue; + bool prohibited_by_policy = IsProhibitedByPolicy(network); info->image = network_icon::GetImageForNetwork(network, network_icon::ICON_TYPE_LIST); info->label = @@ -96,7 +129,12 @@ info->highlight = network->IsConnectedState() || network->IsConnectingState(); info->disable = - network->activation_state() == shill::kActivationStateActivating; + (network->activation_state() == shill::kActivationStateActivating) || + prohibited_by_policy; + if (prohibited_by_policy) { + info->tooltip = + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED); + } if (!animating && network->IsConnectingState()) animating = true; }
diff --git a/ui/chromeos/ui_chromeos.gyp b/ui/chromeos/ui_chromeos.gyp index 2aeec8c..ea0c3dc4 100644 --- a/ui/chromeos/ui_chromeos.gyp +++ b/ui/chromeos/ui_chromeos.gyp
@@ -50,6 +50,7 @@ '../../chromeos/chromeos.gyp:chromeos', '../../chromeos/chromeos.gyp:power_manager_proto', '../../components/components.gyp:device_event_log_component', + '../../components/components.gyp:onc_component', '../../skia/skia.gyp:skia', '../aura/aura.gyp:aura', '../base/ime/ui_base_ime.gyp:ui_base_ime',
diff --git a/ui/chromeos/ui_chromeos_strings.grd b/ui/chromeos/ui_chromeos_strings.grd index 7e36839..67f0971 100644 --- a/ui/chromeos/ui_chromeos_strings.grd +++ b/ui/chromeos/ui_chromeos_strings.grd
@@ -150,6 +150,12 @@ <message name="IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED" desc="Description in status area or network list when no network is connected."> No network </message> + <message name="IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED" desc="Tooltip in network list when no network is prohibited by policy."> + This network is disabled by your administrator. + </message> + <message name="IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED_OTHER" desc="Tooltip in network list for joining other network when connecting unmanaged network is prohibited"> + Connecting to other networks is disabled by your administrator. + </message> <message name="IDS_ASH_STATUS_TRAY_NO_NETWORKS" desc="The message to display in the network info bubble when it is otherwise empty."> No network information available
diff --git a/ui/compositor/clip_transform_recorder.cc b/ui/compositor/clip_transform_recorder.cc index ddc70d1..8afd8be2 100644 --- a/ui/compositor/clip_transform_recorder.cc +++ b/ui/compositor/clip_transform_recorder.cc
@@ -20,8 +20,8 @@ } ClipTransformRecorder::~ClipTransformRecorder() { - for (size_t i = 0; i < num_closers_; ++i) { - switch (closers_[i]) { + for (size_t i = num_closers_; i > 0; --i) { + switch (closers_[i - 1]) { case CLIP_RECT: context_.list_->CreateAndAppendItem<cc::EndClipDisplayItem>(); break;
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index fbc801d..b057366 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -137,8 +137,8 @@ settings.initial_debug_state.SetRecordRenderingStats( command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); - if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees)) - settings.use_property_trees = false; + settings.use_property_trees = + command_line->HasSwitch(cc::switches::kEnableCompositorPropertyTrees); settings.use_zero_copy = IsUIZeroCopyEnabled(); settings.renderer_settings.use_rgba_4444_textures =
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 5144ec9..2ec6de9 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -750,6 +750,10 @@ cc_layer_->RequestCopyOfOutput(request.Pass()); } +gfx::Rect Layer::PaintableRegion() { + return gfx::Rect(size()); +} + scoped_refptr<cc::DisplayItemList> Layer::PaintContentsToDisplayList( const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) { @@ -812,8 +816,8 @@ std::string name_; }; -scoped_refptr<base::trace_event::ConvertableToTraceFormat> -Layer::TakeDebugInfo() { +scoped_refptr<base::trace_event::ConvertableToTraceFormat> Layer::TakeDebugInfo( + cc::Layer* layer) { return new LayerDebugInfo(name_); }
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index d6f593a..5d997ae 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -347,6 +347,7 @@ void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request); // ContentLayerClient + gfx::Rect PaintableRegion() override; scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList( const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) override; @@ -369,8 +370,8 @@ bool force_render_surface() const { return force_render_surface_; } // LayerClient - scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo() - override; + scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo( + cc::Layer* layer) override; // LayerAnimationEventObserver void OnAnimationStarted(const cc::AnimationEvent& event) override;
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 935bfa7..a6c14b4 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -692,7 +692,7 @@ std::string name = "\"\'\\/\b\f\n\r\t\n"; layer->set_name(name); scoped_refptr<base::trace_event::ConvertableToTraceFormat> debug_info = - layer->TakeDebugInfo(); + layer->TakeDebugInfo(layer->cc_layer_for_testing()); EXPECT_TRUE(debug_info.get()); std::string json; debug_info->AppendAsTraceFormat(&json);
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn index c0eef3f..71b0c8e 100644 --- a/ui/events/BUILD.gn +++ b/ui/events/BUILD.gn
@@ -373,9 +373,14 @@ ] if (!is_ios) { - sources += [ "gestures/blink/web_gesture_curve_impl_unittest.cc" ] + sources += [ + "blink/input_handler_proxy_unittest.cc", + "blink/input_scroll_elasticity_controller_unittest.cc", + "gestures/blink/web_gesture_curve_impl_unittest.cc", + ] deps += [ "//third_party/WebKit/public:blink_headers", + "//ui/events/blink", "//ui/events/gestures/blink", ] }
diff --git a/ui/events/blink/BUILD.gn b/ui/events/blink/BUILD.gn index 1fa7fef7..acc1f80 100644 --- a/ui/events/blink/BUILD.gn +++ b/ui/events/blink/BUILD.gn
@@ -6,9 +6,16 @@ sources = [ "blink_event_util.cc", "blink_event_util.h", + "input_handler_proxy.cc", + "input_handler_proxy.h", + "input_handler_proxy_client.h", + "input_scroll_elasticity_controller.cc", + "input_scroll_elasticity_controller.h", + "synchronous_input_handler_proxy.h", ] deps = [ + "//cc:cc", "//third_party/WebKit/public:blink_headers", "//ui/events", "//ui/events:gesture_detection",
diff --git a/ui/events/blink/DEPS b/ui/events/blink/DEPS index c28eb31b..6fa4026a 100644 --- a/ui/events/blink/DEPS +++ b/ui/events/blink/DEPS
@@ -1,3 +1,16 @@ include_rules = [ + "+cc/input/input_handler.h", + "+cc/input/scroll_elasticity_helper.h", + "+cc/trees/swap_promise_monitor.h", + + "+third_party/WebKit/public/platform/WebGestureCurve.h", + "+third_party/WebKit/public/platform/WebGestureCurveTarget.h", + "+third_party/WebKit/public/platform/WebFloatPoint.h", + "+third_party/WebKit/public/platform/WebFloatSize.h", + "+third_party/WebKit/public/platform/WebPoint.h", + "+third_party/WebKit/public/web/WebActiveWheelFlingParameters.h", "+third_party/WebKit/public/web/WebInputEvent.h", + + "+ui/gfx/geometry", + "+ui/events" ]
diff --git a/ui/events/blink/OWNERS b/ui/events/blink/OWNERS new file mode 100644 index 0000000..2328e39d --- /dev/null +++ b/ui/events/blink/OWNERS
@@ -0,0 +1,2 @@ +aelias@chromium.org +tdresser@chromium.org \ No newline at end of file
diff --git a/ui/events/blink/events_blink.gyp b/ui/events/blink/events_blink.gyp new file mode 100644 index 0000000..8b1b8fa --- /dev/null +++ b/ui/events/blink/events_blink.gyp
@@ -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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + # GN version: //ui/events/blink + 'target_name': 'events_blink', + 'type': 'static_library', + 'dependencies': [ + '../../../cc/cc.gyp:cc', + '../../../third_party/WebKit/public/blink_headers.gyp:blink_headers', + '../../gfx/gfx.gyp:gfx_geometry', + '../events.gyp:events', + '../events.gyp:gesture_detection', + ], + 'sources': [ + # Note: sources list duplicated in GN build. + 'blink_event_util.cc', + 'blink_event_util.h', + 'input_handler_proxy_client.h', + 'input_handler_proxy.cc', + 'input_handler_proxy.h', + 'input_scroll_elasticity_controller.cc', + 'input_scroll_elasticity_controller.h', + 'synchronous_input_handler_proxy.h', + ], + }, + ], +} \ No newline at end of file
diff --git a/content/renderer/input/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc similarity index 96% rename from content/renderer/input/input_handler_proxy.cc rename to ui/events/blink/input_handler_proxy.cc index 255492f..852d60b 100644 --- a/content/renderer/input/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.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 "content/renderer/input/input_handler_proxy.h" +#include "ui/events/blink/input_handler_proxy.h" #include <algorithm> @@ -14,13 +14,9 @@ #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" -#include "content/common/input/did_overscroll_params.h" -#include "content/common/input/web_input_event_traits.h" -#include "content/public/common/content_switches.h" -#include "content/renderer/input/input_handler_proxy_client.h" -#include "content/renderer/input/input_scroll_elasticity_controller.h" -#include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/blink/input_handler_proxy_client.h" +#include "ui/events/blink/input_scroll_elasticity_controller.h" #include "ui/events/latency_info.h" #include "ui/gfx/geometry/point_conversions.h" @@ -178,7 +174,7 @@ } // namespace -namespace content { +namespace ui { InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler, InputHandlerProxyClient* client) @@ -196,11 +192,10 @@ disallow_horizontal_fling_scroll_(false), disallow_vertical_fling_scroll_(false), has_fling_animation_started_(false), + smooth_scroll_enabled_(false), uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()) { DCHECK(client); input_handler_->BindToClient(this); - smooth_scroll_enabled_ = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableSmoothScrolling); cc::ScrollElasticityHelper* scroll_elasticity_helper = input_handler_->CreateScrollElasticityHelper(); if (scroll_elasticity_helper) { @@ -241,8 +236,6 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( const WebInputEvent& event) { DCHECK(input_handler_); - TRACE_EVENT1("input,benchmark", "InputHandlerProxy::HandleInputEvent", - "type", WebInputEventTraits::GetName(event.type)); if (FilterInputEventForFlingBoosting(event)) return DID_HANDLE; @@ -870,24 +863,20 @@ "dy", scroll_result.unused_scroll_delta.y()); - DidOverscrollParams params; - params.accumulated_overscroll = scroll_result.accumulated_root_overscroll; - params.latest_overscroll_delta = scroll_result.unused_scroll_delta; - params.current_fling_velocity = - ToClientScrollIncrement(current_fling_velocity_); - params.causal_event_viewport_point = gfx::PointF(causal_event_viewport_point); - if (fling_curve_) { static const int kFlingOverscrollThreshold = 1; disallow_horizontal_fling_scroll_ |= - std::abs(params.accumulated_overscroll.x()) >= + std::abs(scroll_result.accumulated_root_overscroll.x()) >= kFlingOverscrollThreshold; disallow_vertical_fling_scroll_ |= - std::abs(params.accumulated_overscroll.y()) >= + std::abs(scroll_result.accumulated_root_overscroll.y()) >= kFlingOverscrollThreshold; } - client_->DidOverscroll(params); + client_->DidOverscroll(scroll_result.accumulated_root_overscroll, + scroll_result.unused_scroll_delta, + ToClientScrollIncrement(current_fling_velocity_), + gfx::PointF(causal_event_viewport_point)); } bool InputHandlerProxy::CancelCurrentFling() { @@ -1045,4 +1034,4 @@ return did_scroll; } -} // namespace content +} // namespace ui
diff --git a/content/renderer/input/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h similarity index 89% rename from content/renderer/input/input_handler_proxy.h rename to ui/events/blink/input_handler_proxy.h index d234511..fdee704 100644 --- a/content/renderer/input/input_handler_proxy.h +++ b/ui/events/blink/input_handler_proxy.h
@@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_ -#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_ +#ifndef UI_EVENTS_BLINK_INPUT_HANDLER_PROXY_H_ +#define UI_EVENTS_BLINK_INPUT_HANDLER_PROXY_H_ #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/memory/scoped_ptr.h" #include "cc/input/input_handler.h" -#include "content/common/content_export.h" -#include "content/renderer/input/synchronous_input_handler_proxy.h" #include "third_party/WebKit/public/platform/WebGestureCurve.h" #include "third_party/WebKit/public/platform/WebGestureCurveTarget.h" #include "third_party/WebKit/public/web/WebActiveWheelFlingParameters.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/blink/input_scroll_elasticity_controller.h" +#include "ui/events/blink/synchronous_input_handler_proxy.h" -namespace content { +namespace ui { namespace test { class InputHandlerProxyTest; @@ -24,16 +24,19 @@ class InputHandlerProxyClient; class InputScrollElasticityController; +class SynchronousInputHandler; +class SynchronousInputHandlerProxy; -// This class is a proxy between the content input event filtering and the -// compositor's input handling logic. InputHandlerProxy instances live entirely -// on the compositor thread. Each InputHandler instance handles input events -// intended for a specific WebWidget. -class CONTENT_EXPORT InputHandlerProxy +// This class is a proxy between the blink web input events for a WebWidget and +// the compositor's input handling logic. InputHandlerProxy instances live +// entirely on the compositor thread. Each InputHandler instance handles input +// events intended for a specific WebWidget. +class InputHandlerProxy : public cc::InputHandlerClient, public SynchronousInputHandlerProxy, public NON_EXPORTED_BASE(blink::WebGestureCurveTarget) { public: + InputHandlerProxy(cc::InputHandler* input_handler, InputHandlerProxyClient* client); ~InputHandlerProxy() override; @@ -42,6 +45,8 @@ return scroll_elasticity_controller_.get(); } + void set_smooth_scroll_enabled(bool value) { smooth_scroll_enabled_ = value; } + enum EventDisposition { DID_HANDLE, DID_NOT_HANDLE, @@ -184,6 +189,6 @@ DISALLOW_COPY_AND_ASSIGN(InputHandlerProxy); }; -} // namespace content +} // namespace ui -#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_ +#endif // UI_EVENTS_BLINK_INPUT_HANDLER_PROXY_H_
diff --git a/content/renderer/input/input_handler_proxy_client.h b/ui/events/blink/input_handler_proxy_client.h similarity index 72% rename from content/renderer/input/input_handler_proxy_client.h rename to ui/events/blink/input_handler_proxy_client.h index 53b4bc9..34ce9fe 100644 --- a/content/renderer/input/input_handler_proxy_client.h +++ b/ui/events/blink/input_handler_proxy_client.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 CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_ -#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_ +#ifndef UI_EVENTS_BLINK_INPUT_HANDLER_PROXY_CLIENT_H_ +#define UI_EVENTS_BLINK_INPUT_HANDLER_PROXY_CLIENT_H_ namespace blink { class WebGestureCurve; @@ -12,9 +12,7 @@ struct WebSize; } -namespace content { - -struct DidOverscrollParams; +namespace ui { // All callbacks invoked from the compositor thread. class InputHandlerProxyClient { @@ -34,7 +32,11 @@ const blink::WebFloatPoint& velocity, const blink::WebSize& cumulative_scroll) = 0; - virtual void DidOverscroll(const DidOverscrollParams& params) = 0; + virtual void DidOverscroll( + const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta, + const gfx::Vector2dF& current_fling_velocity, + const gfx::PointF& causal_event_viewport_point) = 0; virtual void DidStopFlinging() = 0; @@ -44,6 +46,6 @@ virtual ~InputHandlerProxyClient() {} }; -} // namespace content +} // namespace ui -#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_ +#endif // UI_EVENTS_BLINK_INPUT_HANDLER_PROXY_CLIENT_H_
diff --git a/content/renderer/input/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc similarity index 97% rename from content/renderer/input/input_handler_proxy_unittest.cc rename to ui/events/blink/input_handler_proxy_unittest.cc index aee95d8..3da09e3 100644 --- a/content/renderer/input/input_handler_proxy_unittest.cc +++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/input/input_handler_proxy.h" +#include "ui/events/blink/input_handler_proxy.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "cc/trees/swap_promise_monitor.h" -#include "content/common/input/did_overscroll_params.h" -#include "content/renderer/input/input_handler_proxy_client.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebFloatPoint.h" @@ -16,6 +14,7 @@ #include "third_party/WebKit/public/platform/WebGestureCurve.h" #include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/blink/input_handler_proxy_client.h" #include "ui/events/latency_info.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size_f.h" @@ -34,7 +33,7 @@ using blink::WebTouchPoint; using testing::Field; -namespace content { +namespace ui { namespace test { namespace { @@ -150,7 +149,7 @@ DISALLOW_COPY_AND_ASSIGN(MockInputHandler); }; -class MockSynchronousInputHandler : public content::SynchronousInputHandler { +class MockSynchronousInputHandler : public SynchronousInputHandler { public: MOCK_METHOD0(SetNeedsSynchronousAnimateInput, void()); MOCK_METHOD6(UpdateRootLayerState, @@ -193,7 +192,7 @@ }; class MockInputHandlerProxyClient - : public content::InputHandlerProxyClient { + : public InputHandlerProxyClient { public: MockInputHandlerProxyClient() {} ~MockInputHandlerProxyClient() override {} @@ -212,7 +211,11 @@ blink::WebFloatSize(cumulative_scroll.width, cumulative_scroll.height)); } - MOCK_METHOD1(DidOverscroll, void(const DidOverscrollParams&)); + MOCK_METHOD4(DidOverscroll, + void(const gfx::Vector2dF& accumulated_overscroll, + const gfx::Vector2dF& latest_overscroll_delta, + const gfx::Vector2dF& current_fling_velocity, + const gfx::PointF& causal_event_viewport_point)); void DidStopFlinging() override {} void DidAnimateForInput() override {} @@ -254,7 +257,8 @@ GetParam() == CHILD_SCROLL_SYNCHRONOUS_HANDLER), expected_disposition_(InputHandlerProxy::DID_HANDLE) { input_handler_.reset( - new content::InputHandlerProxy(&mock_input_handler_, &mock_client_)); + new ui::InputHandlerProxy( + &mock_input_handler_, &mock_client_)); scroll_result_did_scroll_.did_scroll = true; scroll_result_did_not_scroll_.did_scroll = false; @@ -358,7 +362,7 @@ testing::StrictMock<MockInputHandler> mock_input_handler_; testing::StrictMock<MockSynchronousInputHandler> mock_synchronous_input_handler_; - scoped_ptr<content::InputHandlerProxy> input_handler_; + scoped_ptr<ui::InputHandlerProxy> input_handler_; testing::StrictMock<MockInputHandlerProxyClient> mock_client_; WebGestureEvent gesture_; InputHandlerProxy::EventDisposition expected_disposition_; @@ -1510,16 +1514,11 @@ .WillOnce(testing::Return(overscroll)); EXPECT_CALL( mock_client_, - DidOverscroll(testing::AllOf( - testing::Field( - &DidOverscrollParams::accumulated_overscroll, - testing::Eq(overscroll.accumulated_root_overscroll)), - testing::Field( - &DidOverscrollParams::latest_overscroll_delta, - testing::Eq(overscroll.unused_scroll_delta)), - testing::Field( - &DidOverscrollParams::current_fling_velocity, - testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))))); + DidOverscroll( + overscroll.accumulated_root_overscroll, + overscroll.unused_scroll_delta, + testing::Property(&gfx::Vector2dF::y, testing::Lt(0)), + testing::_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_SET_NEEDS_ANIMATE_INPUT(1); time += base::TimeDelta::FromMilliseconds(100); @@ -1670,16 +1669,11 @@ .WillOnce(testing::Return(overscroll)); EXPECT_CALL( mock_client_, - DidOverscroll(testing::AllOf( - testing::Field( - &DidOverscrollParams::accumulated_overscroll, - testing::Eq(overscroll.accumulated_root_overscroll)), - testing::Field( - &DidOverscrollParams::latest_overscroll_delta, - testing::Eq(overscroll.unused_scroll_delta)), - testing::Field( - &DidOverscrollParams::current_fling_velocity, - testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))))); + DidOverscroll( + overscroll.accumulated_root_overscroll, + overscroll.unused_scroll_delta, + testing::Property(&gfx::Vector2dF::y, testing::Lt(0)), + testing::_)); EXPECT_SET_NEEDS_ANIMATE_INPUT(1); time += base::TimeDelta::FromMilliseconds(10); Animate(time); @@ -1704,16 +1698,11 @@ .WillOnce(testing::Return(overscroll)); EXPECT_CALL( mock_client_, - DidOverscroll(testing::AllOf( - testing::Field( - &DidOverscrollParams::accumulated_overscroll, - testing::Eq(overscroll.accumulated_root_overscroll)), - testing::Field( - &DidOverscrollParams::latest_overscroll_delta, - testing::Eq(overscroll.unused_scroll_delta)), - testing::Field( - &DidOverscrollParams::current_fling_velocity, - testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))))); + DidOverscroll( + overscroll.accumulated_root_overscroll, + overscroll.unused_scroll_delta, + testing::Property(&gfx::Vector2dF::x, testing::Lt(0)), + testing::_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(10); Animate(time); @@ -2373,7 +2362,8 @@ testing::StrictMock<MockInputHandlerProxyClientWithDidAnimateForInput> mock_client; input_handler_.reset( - new content::InputHandlerProxy(&mock_input_handler_, &mock_client)); + new ui::InputHandlerProxy( + &mock_input_handler_, &mock_client)); if (install_synchronous_handler_) { EXPECT_CALL(mock_input_handler_, RequestUpdateForSynchronousInputHandler()) .Times(1); @@ -2407,7 +2397,7 @@ testing::StrictMock<MockInputHandlerProxyClient> mock_client; testing::StrictMock<MockSynchronousInputHandler> mock_synchronous_input_handler; - content::InputHandlerProxy proxy(&mock_input_handler, &mock_client); + ui::InputHandlerProxy proxy(&mock_input_handler, &mock_client); // When adding a SynchronousInputHandler, immediately request an // UpdateRootLayerStateForSynchronousInputHandler() call. @@ -2433,7 +2423,7 @@ testing::StrictMock<MockInputHandlerProxyClient> mock_client; testing::StrictMock<MockSynchronousInputHandler> mock_synchronous_input_handler; - content::InputHandlerProxy proxy(&mock_input_handler, &mock_client); + ui::InputHandlerProxy proxy(&mock_input_handler, &mock_client); proxy.SetOnlySynchronouslyAnimateRootFlings(&mock_synchronous_input_handler); @@ -2458,7 +2448,7 @@ testing::StrictMock<MockInputHandlerProxyClient> mock_client; testing::StrictMock<MockSynchronousInputHandler> mock_synchronous_input_handler; - content::InputHandlerProxy proxy(&mock_input_handler, &mock_client); + ui::InputHandlerProxy proxy(&mock_input_handler, &mock_client); proxy.SetOnlySynchronouslyAnimateRootFlings(&mock_synchronous_input_handler); @@ -2475,4 +2465,4 @@ InputHandlerProxyTest, testing::ValuesIn(test_types)); } // namespace test -} // namespace content +} // namespace ui
diff --git a/content/renderer/input/input_scroll_elasticity_controller.cc b/ui/events/blink/input_scroll_elasticity_controller.cc similarity index 98% rename from content/renderer/input/input_scroll_elasticity_controller.cc rename to ui/events/blink/input_scroll_elasticity_controller.cc index 00d078ff..bdd1808 100644 --- a/content/renderer/input/input_scroll_elasticity_controller.cc +++ b/ui/events/blink/input_scroll_elasticity_controller.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 "content/renderer/input/input_scroll_elasticity_controller.h" +#include "ui/events/blink/input_scroll_elasticity_controller.h" #include <math.h> @@ -37,7 +37,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -namespace content { +namespace ui { namespace { @@ -407,4 +407,4 @@ } } -} // namespace content +} // namespace ui
diff --git a/content/renderer/input/input_scroll_elasticity_controller.h b/ui/events/blink/input_scroll_elasticity_controller.h similarity index 94% rename from content/renderer/input/input_scroll_elasticity_controller.h rename to ui/events/blink/input_scroll_elasticity_controller.h index c60a86e..8c64681 100644 --- a/content/renderer/input/input_scroll_elasticity_controller.h +++ b/ui/events/blink/input_scroll_elasticity_controller.h
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ -#define CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ +#ifndef UI_EVENTS_BLINK_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ +#define UI_EVENTS_BLINK_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "cc/input/scroll_elasticity_helper.h" -#include "content/common/content_export.h" #include "third_party/WebKit/public/web/WebInputEvent.h" // InputScrollElasticityController is based on @@ -42,9 +41,9 @@ struct InputHandlerScrollResult; } // namespace cc -namespace content { +namespace ui { -class CONTENT_EXPORT InputScrollElasticityController { +class InputScrollElasticityController { public: explicit InputScrollElasticityController(cc::ScrollElasticityHelper* helper); virtual ~InputScrollElasticityController(); @@ -143,6 +142,6 @@ DISALLOW_COPY_AND_ASSIGN(InputScrollElasticityController); }; -} // namespace content +} // namespace ui -#endif // CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_ +#endif // UI_EVENTS_BLINK_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_
diff --git a/content/renderer/input/input_scroll_elasticity_controller_unittest.cc b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc similarity index 98% rename from content/renderer/input/input_scroll_elasticity_controller_unittest.cc rename to ui/events/blink/input_scroll_elasticity_controller_unittest.cc index fa2c7f19..51fe4ff 100644 --- a/content/renderer/input/input_scroll_elasticity_controller_unittest.cc +++ b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/events/blink/input_scroll_elasticity_controller.h" + #include "cc/input/input_handler.h" -#include "content/renderer/input/input_scroll_elasticity_controller.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -namespace content { +namespace ui { namespace { enum Phase { @@ -384,4 +385,4 @@ } } // namespace -} // namespace content +} // namespace ui
diff --git a/content/renderer/input/synchronous_input_handler_proxy.h b/ui/events/blink/synchronous_input_handler_proxy.h similarity index 86% rename from content/renderer/input/synchronous_input_handler_proxy.h rename to ui/events/blink/synchronous_input_handler_proxy.h index 3bf3990..36485f0 100644 --- a/content/renderer/input/synchronous_input_handler_proxy.h +++ b/ui/events/blink/synchronous_input_handler_proxy.h
@@ -2,20 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_INPUT_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ -#define CONTENT_RENDERER_INPUT_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ +#ifndef UI_EVENTS_BLINK_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ +#define UI_EVENTS_BLINK_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ #include "base/time/time.h" -#include "content/common/content_export.h" namespace gfx { class ScrollOffset; class SizeF; } -namespace content { +namespace ui { -class CONTENT_EXPORT SynchronousInputHandler { +class SynchronousInputHandler { public: virtual ~SynchronousInputHandler() {} @@ -40,7 +39,7 @@ // This interface provides support for that behaviour. The WebView embedder will // act as the InputHandler for controlling the timing of input (fling) // animations. -class CONTENT_EXPORT SynchronousInputHandlerProxy { +class SynchronousInputHandlerProxy { public: virtual ~SynchronousInputHandlerProxy() {} @@ -68,6 +67,6 @@ const gfx::ScrollOffset& root_offset) = 0; }; -} // namespace content +} // namespace ui -#endif // CONTENT_RENDERER_INPUT_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ +#endif // UI_EVENTS_BLINK_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_
diff --git a/ui/events/events.gyp b/ui/events/events.gyp index 8a15401..82cd006 100644 --- a/ui/events/events.gyp +++ b/ui/events/events.gyp
@@ -211,22 +211,6 @@ ], }, { - # GN version: //ui/events/blink - 'target_name': 'blink', - 'type': 'static_library', - 'dependencies': [ - '../../third_party/WebKit/public/blink_headers.gyp:blink_headers', - '../gfx/gfx.gyp:gfx_geometry', - 'events', - 'gesture_detection', - ], - 'sources': [ - # Note: sources list duplicated in GN build. - 'blink/blink_event_util.cc', - 'blink/blink_event_util.h', - ], - }, - { # GN version: //ui/events/gestures/blink 'target_name': 'gestures_blink', 'type': 'static_library', @@ -383,122 +367,6 @@ }], ], }, - { - # GN version: //ui/events:events_unittests - 'target_name': 'events_unittests', - 'type': '<(gtest_target_type)', - 'dependencies': [ - '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/base/base.gyp:run_all_unittests', - '<(DEPTH)/base/base.gyp:test_support_base', - '<(DEPTH)/ipc/ipc.gyp:test_support_ipc', - '<(DEPTH)/skia/skia.gyp:skia', - '<(DEPTH)/testing/gtest.gyp:gtest', - '<(DEPTH)/third_party/mesa/mesa.gyp:osmesa', - '../gfx/gfx.gyp:gfx', - '../gfx/gfx.gyp:gfx_geometry', - '../gfx/gfx.gyp:gfx_test_support', - 'devices/events_devices.gyp:events_devices', - 'dom_keycode_converter', - 'events', - 'events_base', - 'events_ipc', - 'events_test_support', - 'gesture_detection', - 'gestures_blink', - 'platform/events_platform.gyp:events_platform', - ], - 'sources': [ - # Note: sources list duplicated in GN build. - 'android/scroller_unittest.cc', - 'cocoa/events_mac_unittest.mm', - 'devices/x11/device_data_manager_x11_unittest.cc', - 'event_dispatcher_unittest.cc', - 'event_processor_unittest.cc', - 'event_rewriter_unittest.cc', - 'event_unittest.cc', - 'gesture_detection/bitset_32_unittest.cc', - 'gesture_detection/filtered_gesture_provider_unittest.cc', - 'gesture_detection/gesture_event_data_packet_unittest.cc', - 'gesture_detection/gesture_provider_unittest.cc', - 'gesture_detection/motion_event_buffer_unittest.cc', - 'gesture_detection/motion_event_generic_unittest.cc', - 'gesture_detection/snap_scroll_controller_unittest.cc', - 'gesture_detection/touch_disposition_gesture_filter_unittest.cc', - 'gesture_detection/velocity_tracker_unittest.cc', - 'gestures/blink/web_gesture_curve_impl_unittest.cc', - 'gestures/fling_curve_unittest.cc', - 'gestures/gesture_provider_aura_unittest.cc', - 'gestures/motion_event_aura_unittest.cc', - 'ipc/latency_info_param_traits_unittest.cc', - 'keycodes/dom/keycode_converter_unittest.cc', - 'keycodes/keyboard_code_conversion_unittest.cc', - 'latency_info_unittest.cc', - 'platform/platform_event_source_unittest.cc', - 'x/events_x_unittest.cc', - ], - 'include_dirs': [ - '../../testing/gmock/include', - ], - 'conditions': [ - ['use_x11==1', { - 'dependencies': [ - '../../build/linux/system.gyp:x11', - '../gfx/x/gfx_x11.gyp:gfx_x11', - ], - }], - ['use_ozone==1', { - 'sources': [ - 'ozone/chromeos/cursor_controller_unittest.cc', - 'ozone/evdev/event_converter_evdev_impl_unittest.cc', - 'ozone/evdev/event_converter_test_util.cc', - 'ozone/evdev/event_device_info_unittest.cc', - 'ozone/evdev/event_device_test_util.cc', - 'ozone/evdev/input_injector_evdev_unittest.cc', - 'ozone/evdev/tablet_event_converter_evdev_unittest.cc', - 'ozone/evdev/touch_event_converter_evdev_unittest.cc', - 'ozone/evdev/touch_noise/touch_noise_finder_unittest.cc', - ], - 'dependencies': [ - 'ozone/events_ozone.gyp:events_ozone', - 'ozone/events_ozone.gyp:events_ozone_evdev', - 'ozone/events_ozone.gyp:events_ozone_layout', - ] - }], - ['use_xkbcommon==1', { - 'sources': [ - 'ozone/layout/keyboard_layout_engine_unittest.cc', - 'ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc', - ] - }], - ['use_aura==0', { - 'sources!': [ - 'gestures/gesture_provider_aura_unittest.cc', - 'gestures/motion_event_aura_unittest.cc', - ], - }], - ['OS=="linux" and use_allocator!="none"', { - 'dependencies': [ - '<(DEPTH)/base/allocator/allocator.gyp:allocator', - ], - }], - # Exclude tests that rely on event_utils.h for platforms that do not - # provide native cracking, i.e., platforms that use events_stub.cc. - ['OS!="win" and use_x11!=1 and use_ozone!=1', { - 'sources!': [ - 'event_unittest.cc', - ], - }], - ['OS == "android"', { - 'sources': [ - 'android/motion_event_android_unittest.cc', - ], - 'dependencies': [ - '../../testing/android/native_test.gyp:native_test_native_code', - ], - }], - ], - }, ], 'conditions': [ ['OS == "android"', { @@ -512,61 +380,7 @@ }, 'includes': [ '../../build/jar_file_jni_generator.gypi' ], }, - { - 'target_name': 'events_unittests_apk', - 'type': 'none', - 'dependencies': [ - 'events_unittests', - ], - 'variables': { - 'test_suite_name': 'events_unittests', - }, - 'includes': [ '../../build/apk_test.gypi' ], - }, - ], - 'conditions': [ - ['test_isolation_mode != "noop"', { - 'targets': [ - { - 'target_name': 'events_unittests_apk_run', - 'type': 'none', - 'dependencies': [ - 'events_unittests_apk', - ], - 'includes': [ - '../../build/isolate.gypi', - ], - 'sources': [ - 'events_unittests_apk.isolate', - ], - }, - ], - }], - ], - }], - ['test_isolation_mode != "noop"', { - 'targets': [ - { - 'target_name': 'events_unittests_run', - 'type': 'none', - 'dependencies': [ - 'events_unittests', - ], - 'includes': [ - '../../build/isolate.gypi', - ], - 'sources': [ - 'events_unittests.isolate', - ], - 'conditions': [ - ['use_x11 == 1', { - 'dependencies': [ - '../../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck', - ], - }], - ], - }, ], }], ], -} +} \ No newline at end of file
diff --git a/ui/events/events_unittests.gyp b/ui/events/events_unittests.gyp new file mode 100644 index 0000000..f7e5a67 --- /dev/null +++ b/ui/events/events_unittests.gyp
@@ -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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + # GN version: //ui/events:events_unittests + 'target_name': 'events_unittests', + 'type': '<(gtest_target_type)', + 'dependencies': [ + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/base/base.gyp:run_all_unittests', + '<(DEPTH)/base/base.gyp:test_support_base', + '<(DEPTH)/ipc/ipc.gyp:test_support_ipc', + '<(DEPTH)/skia/skia.gyp:skia', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/mesa/mesa.gyp:osmesa', + '../gfx/gfx.gyp:gfx', + '../gfx/gfx.gyp:gfx_geometry', + '../gfx/gfx.gyp:gfx_test_support', + 'devices/events_devices.gyp:events_devices', + 'events.gyp:dom_keycode_converter', + 'events.gyp:events', + 'events.gyp:events_base', + 'events.gyp:events_ipc', + 'events.gyp:events_test_support', + 'events.gyp:gesture_detection', + 'events.gyp:gestures_blink', + 'platform/events_platform.gyp:events_platform', + ], + 'sources': [ + # Note: sources list duplicated in GN build. + 'android/scroller_unittest.cc', + 'cocoa/events_mac_unittest.mm', + 'devices/x11/device_data_manager_x11_unittest.cc', + 'event_dispatcher_unittest.cc', + 'event_processor_unittest.cc', + 'event_rewriter_unittest.cc', + 'event_unittest.cc', + 'gesture_detection/bitset_32_unittest.cc', + 'gesture_detection/filtered_gesture_provider_unittest.cc', + 'gesture_detection/gesture_event_data_packet_unittest.cc', + 'gesture_detection/gesture_provider_unittest.cc', + 'gesture_detection/motion_event_buffer_unittest.cc', + 'gesture_detection/motion_event_generic_unittest.cc', + 'gesture_detection/snap_scroll_controller_unittest.cc', + 'gesture_detection/touch_disposition_gesture_filter_unittest.cc', + 'gesture_detection/velocity_tracker_unittest.cc', + 'gestures/blink/web_gesture_curve_impl_unittest.cc', + 'gestures/fling_curve_unittest.cc', + 'gestures/gesture_provider_aura_unittest.cc', + 'gestures/motion_event_aura_unittest.cc', + 'ipc/latency_info_param_traits_unittest.cc', + 'keycodes/dom/keycode_converter_unittest.cc', + 'keycodes/keyboard_code_conversion_unittest.cc', + 'latency_info_unittest.cc', + 'platform/platform_event_source_unittest.cc', + 'x/events_x_unittest.cc', + ], + 'include_dirs': [ + '../../testing/gmock/include', + ], + 'conditions': [ + ['use_x11==1', { + 'dependencies': [ + '../../build/linux/system.gyp:x11', + '../gfx/x/gfx_x11.gyp:gfx_x11', + ], + }], + ['use_ozone==1', { + 'sources': [ + 'ozone/chromeos/cursor_controller_unittest.cc', + 'ozone/evdev/event_converter_evdev_impl_unittest.cc', + 'ozone/evdev/event_converter_test_util.cc', + 'ozone/evdev/event_device_info_unittest.cc', + 'ozone/evdev/event_device_test_util.cc', + 'ozone/evdev/input_injector_evdev_unittest.cc', + 'ozone/evdev/tablet_event_converter_evdev_unittest.cc', + 'ozone/evdev/touch_event_converter_evdev_unittest.cc', + 'ozone/evdev/touch_noise/touch_noise_finder_unittest.cc', + ], + 'dependencies': [ + 'ozone/events_ozone.gyp:events_ozone', + 'ozone/events_ozone.gyp:events_ozone_evdev', + 'ozone/events_ozone.gyp:events_ozone_layout', + ] + }], + ['use_xkbcommon==1', { + 'sources': [ + 'ozone/layout/keyboard_layout_engine_unittest.cc', + 'ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc', + ] + }], + ['use_aura==0', { + 'sources!': [ + 'gestures/gesture_provider_aura_unittest.cc', + 'gestures/motion_event_aura_unittest.cc', + ], + }], + ['OS=="linux" and use_allocator!="none"', { + 'dependencies': [ + '<(DEPTH)/base/allocator/allocator.gyp:allocator', + ], + }], + # Exclude tests that rely on event_utils.h for platforms that do not + # provide native cracking, i.e., platforms that use events_stub.cc. + ['OS!="win" and use_x11!=1 and use_ozone!=1', { + 'sources!': [ + 'event_unittest.cc', + ], + }], + ['OS == "android"', { + 'sources': [ + 'android/motion_event_android_unittest.cc', + ], + 'dependencies': [ + '../../testing/android/native_test.gyp:native_test_native_code', + ], + }], + ['OS!="ios"', { + 'sources': [ + 'blink/input_handler_proxy_unittest.cc', + 'blink/input_scroll_elasticity_controller_unittest.cc', + ], + 'dependencies': [ + 'blink/events_blink.gyp:events_blink', + ], + }], + ], + }, + ], + 'conditions': [ + ['OS == "android"', { + 'targets': [ + { + 'target_name': 'events_unittests_apk', + 'type': 'none', + 'dependencies': [ + 'events_unittests', + ], + 'variables': { + 'test_suite_name': 'events_unittests', + }, + 'includes': [ '../../build/apk_test.gypi' ], + }, + ], + 'conditions': [ + ['test_isolation_mode != "noop"', { + 'targets': [ + { + 'target_name': 'events_unittests_apk_run', + 'type': 'none', + 'dependencies': [ + 'events_unittests_apk', + ], + 'includes': [ + '../../build/isolate.gypi', + ], + 'sources': [ + 'events_unittests_apk.isolate', + ], + }, + ], + }], + ], + }], + ['test_isolation_mode != "noop"', { + 'targets': [ + { + 'target_name': 'events_unittests_run', + 'type': 'none', + 'dependencies': [ + 'events_unittests', + ], + 'includes': [ + '../../build/isolate.gypi', + ], + 'sources': [ + 'events_unittests.isolate', + ], + 'conditions': [ + ['use_x11 == 1', { + 'dependencies': [ + '../../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck', + ], + }], + ], + }, + ], + }], + ], +} \ No newline at end of file
diff --git a/ui/events/latency_info.cc b/ui/events/latency_info.cc index e8bdbd37..33f51721 100644 --- a/ui/events/latency_info.cc +++ b/ui/events/latency_info.cc
@@ -113,17 +113,19 @@ : value_(value) { } -struct BenchmarkEnabledInitializer { - BenchmarkEnabledInitializer() : - benchmark_enabled(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( - "benchmark")) { +const char kTraceCategoriesForAsyncEvents[] = "benchmark,latencyInfo"; + +struct LatencyInfoEnabledInitializer { + LatencyInfoEnabledInitializer() : + latency_info_enabled(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( + kTraceCategoriesForAsyncEvents)) { } - const unsigned char* benchmark_enabled; + const unsigned char* latency_info_enabled; }; -static base::LazyInstance<BenchmarkEnabledInitializer>::Leaky - g_benchmark_enabled = LAZY_INSTANCE_INITIALIZER; +static base::LazyInstance<LatencyInfoEnabledInitializer>::Leaky + g_latency_info_enabled = LAZY_INSTANCE_INITIALIZER; } // namespace @@ -222,15 +224,15 @@ uint32 event_count, const char* trace_name_str) { - const unsigned char* benchmark_enabled = - g_benchmark_enabled.Get().benchmark_enabled; + const unsigned char* latency_info_enabled = + g_latency_info_enabled.Get().latency_info_enabled; if (IsBeginComponent(component)) { // Should only ever add begin component once. CHECK_EQ(-1, trace_id_); trace_id_ = component_sequence_number; - if (*benchmark_enabled) { + if (*latency_info_enabled) { // The timestamp for ASYNC_BEGIN trace event is used for drawing the // beginning of the trace event in trace viewer. For better visualization, // for an input event, we want to draw the beginning as when the event is @@ -257,7 +259,7 @@ } TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0( - "benchmark,latencyInfo", + kTraceCategoriesForAsyncEvents, trace_name_.c_str(), TRACE_ID_DONT_MANGLE(trace_id_), ts); @@ -294,11 +296,12 @@ CHECK(!terminated_); terminated_ = true; - if (*benchmark_enabled) { - TRACE_EVENT_COPY_ASYNC_END2("benchmark,latencyInfo", trace_name_.c_str(), - TRACE_ID_DONT_MANGLE(trace_id_), "data", - AsTraceableData(), "coordinates", - CoordinatesAsTraceableData()); + if (*latency_info_enabled) { + TRACE_EVENT_COPY_ASYNC_END2(kTraceCategoriesForAsyncEvents, + trace_name_.c_str(), + TRACE_ID_DONT_MANGLE(trace_id_), + "data", AsTraceableData(), + "coordinates", CoordinatesAsTraceableData()); } TRACE_EVENT_WITH_FLOW0("input,benchmark",
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc index cd769000..1fe2d3ca 100644 --- a/ui/gfx/canvas.cc +++ b/ui/gfx/canvas.cc
@@ -120,7 +120,7 @@ // Make a bitmap to return, and a canvas to draw into it. We don't just want // to call extractSubset or the copy constructor, since we want an actual copy // of the bitmap. - const SkISize size = canvas_->getDeviceSize(); + const SkISize size = canvas_->getBaseLayerSize(); SkBitmap result; result.allocN32Pixels(size.width(), size.height());
diff --git a/ui/gfx/nine_image_painter_unittest.cc b/ui/gfx/nine_image_painter_unittest.cc index 759c7f4..c5b3bd1 100644 --- a/ui/gfx/nine_image_painter_unittest.cc +++ b/ui/gfx/nine_image_painter_unittest.cc
@@ -86,7 +86,7 @@ painter.Paint(&canvas, bounds); SkBitmap result; - const SkISize size = canvas.sk_canvas()->getDeviceSize(); + const SkISize size = canvas.sk_canvas()->getBaseLayerSize(); result.allocN32Pixels(size.width(), size.height()); canvas.sk_canvas()->readPixels(&result, 0, 0); @@ -120,7 +120,7 @@ painter.Paint(&canvas, bounds); SkBitmap result; - const SkISize size = canvas.sk_canvas()->getDeviceSize(); + const SkISize size = canvas.sk_canvas()->getBaseLayerSize(); result.allocN32Pixels(size.width(), size.height()); canvas.sk_canvas()->readPixels(&result, 0, 0); @@ -153,7 +153,7 @@ painter.Paint(&canvas, bounds); SkBitmap result; - const SkISize size = canvas.sk_canvas()->getDeviceSize(); + const SkISize size = canvas.sk_canvas()->getBaseLayerSize(); result.allocN32Pixels(size.width(), size.height()); canvas.sk_canvas()->readPixels(&result, 0, 0); @@ -192,7 +192,7 @@ painter.Paint(&canvas, bounds); SkBitmap result; - const SkISize size = canvas.sk_canvas()->getDeviceSize(); + const SkISize size = canvas.sk_canvas()->getBaseLayerSize(); result.allocN32Pixels(size.width(), size.height()); canvas.sk_canvas()->readPixels(&result, 0, 0); @@ -224,7 +224,7 @@ painter.Paint(&canvas, bounds); SkBitmap result; - const SkISize size = canvas.sk_canvas()->getDeviceSize(); + const SkISize size = canvas.sk_canvas()->getBaseLayerSize(); result.allocN32Pixels(size.width(), size.height()); canvas.sk_canvas()->readPixels(&result, 0, 0);
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc index 231f6c5..459ec723 100644 --- a/ui/gl/gl_surface_ozone.cc +++ b/ui/gl/gl_surface_ozone.cc
@@ -366,10 +366,12 @@ base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, fence_retired_callback, false); - } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { - glFinish(); + return; // Defer frame submission until fence signals. } + if (ozone_surface_->IsUniversalDisplayLinkDevice()) + glFinish(); + frame->ready = true; SubmitFrame(); }
diff --git a/ui/metro_viewer/BUILD.gn b/ui/metro_viewer/BUILD.gn index c2a623d..2223555 100644 --- a/ui/metro_viewer/BUILD.gn +++ b/ui/metro_viewer/BUILD.gn
@@ -13,5 +13,6 @@ deps = [ "//base", + "//ipc", ] }
diff --git a/ui/metro_viewer/metro_viewer.gyp b/ui/metro_viewer/metro_viewer.gyp index 35c6344..c8bafdc 100644 --- a/ui/metro_viewer/metro_viewer.gyp +++ b/ui/metro_viewer/metro_viewer.gyp
@@ -8,6 +8,7 @@ }, 'targets': [ { + # GN version: //ui/metro_viewer 'target_name': 'metro_viewer_messages', 'type': 'static_library', 'dependencies': [
diff --git a/ui/ozone/platform/drm/gpu/drm_window.cc b/ui/ozone/platform/drm/gpu/drm_window.cc index ba752f0..59b2380 100644 --- a/ui/ozone/platform/drm/gpu/drm_window.cc +++ b/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -9,7 +9,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkDevice.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkSurface.h" #include "ui/ozone/common/gpu/ozone_gpu_message_params.h" #include "ui/ozone/platform/drm/common/drm_util.h" @@ -41,8 +41,8 @@ canvas->clear(SK_ColorTRANSPARENT); SkRect clip; - clip.set(0, 0, canvas->getDeviceSize().width(), - canvas->getDeviceSize().height()); + clip.set(0, 0, canvas->getBaseLayerSize().width(), + canvas->getBaseLayerSize().height()); canvas->clipRect(clip, SkRegion::kReplace_Op); canvas->drawBitmapRect(image, damage, NULL); }
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc index 3c068b8..9c8ae91 100644 --- a/ui/views/mus/window_manager_connection.cc +++ b/ui/views/mus/window_manager_connection.cc
@@ -6,6 +6,7 @@ #include "base/lazy_instance.h" #include "base/threading/thread_local.h" +#include "base/threading/thread_restrictions.h" #include "components/mus/public/cpp/window_tree_connection.h" #include "components/mus/public/interfaces/window_tree.mojom.h" #include "mojo/application/public/cpp/application_connection.h" @@ -111,6 +112,8 @@ window_manager_->OpenWindow( window_tree_client.Pass(), mojo::Map<mojo::String, mojo::Array<uint8_t>>::From(properties)); + + base::ThreadRestrictions::ScopedAllowWait allow_wait; mus::WindowTreeConnection* window_tree_connection = mus::WindowTreeConnection::Create( this, window_tree_client_request.Pass(),
diff --git a/ui/views/view.cc b/ui/views/view.cc index 46bb7be..43896614 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -1376,8 +1376,8 @@ void View::OnPaintBackground(gfx::Canvas* canvas) { if (background_.get()) { TRACE_EVENT2("views", "View::OnPaintBackground", - "width", canvas->sk_canvas()->getDevice()->width(), - "height", canvas->sk_canvas()->getDevice()->height()); + "width", canvas->sk_canvas()->getBaseLayerSize().width(), + "height", canvas->sk_canvas()->getBaseLayerSize().height()); background_->Paint(canvas, this); } } @@ -1385,8 +1385,8 @@ void View::OnPaintBorder(gfx::Canvas* canvas) { if (border_.get()) { TRACE_EVENT2("views", "View::OnPaintBorder", - "width", canvas->sk_canvas()->getDevice()->width(), - "height", canvas->sk_canvas()->getDevice()->height()); + "width", canvas->sk_canvas()->getBaseLayerSize().width(), + "height", canvas->sk_canvas()->getBaseLayerSize().height()); border_->Paint(*this, canvas); } }
diff --git a/ui/webui/resources/polymer_resources.grdp b/ui/webui/resources/polymer_resources.grdp index 2ec01b8..615141fe 100644 --- a/ui/webui/resources/polymer_resources.grdp +++ b/ui/webui/resources/polymer_resources.grdp
@@ -23,18 +23,18 @@ <structure name="IDR_POLYMER_1_0_FONT_ROBOTO_ROBOTO_HTML" file="../../../third_party/polymer/v1_0/components-chromium/font-roboto/roboto.html" type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_IRON_A11Y_KEYS_IRON_A11Y_KEYS_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys/iron-a11y-keys-extracted.js" - type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_IRON_A11Y_KEYS_IRON_A11Y_KEYS_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys/iron-a11y-keys.html" - type="chrome_html" /> <structure name="IDR_POLYMER_1_0_IRON_A11Y_KEYS_BEHAVIOR_IRON_A11Y_KEYS_BEHAVIOR_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/iron-a11y-keys-behavior-extracted.js" type="chrome_html" /> <structure name="IDR_POLYMER_1_0_IRON_A11Y_KEYS_BEHAVIOR_IRON_A11Y_KEYS_BEHAVIOR_HTML" file="../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html" type="chrome_html" /> + <structure name="IDR_POLYMER_1_0_IRON_A11Y_KEYS_IRON_A11Y_KEYS_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys/iron-a11y-keys-extracted.js" + type="chrome_html" /> + <structure name="IDR_POLYMER_1_0_IRON_A11Y_KEYS_IRON_A11Y_KEYS_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys/iron-a11y-keys.html" + type="chrome_html" /> <structure name="IDR_POLYMER_1_0_IRON_BEHAVIORS_IRON_BUTTON_STATE_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js" type="chrome_html" /> @@ -404,6 +404,9 @@ <structure name="IDR_POLYMER_1_0_PAPER_DIALOG_BEHAVIOR_PAPER_DIALOG_COMMON_CSS" file="../../../third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-common.css" type="chrome_html" /> + <structure name="IDR_POLYMER_1_0_PAPER_DIALOG_BEHAVIOR_PAPER_DIALOG_SHARED_STYLES_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-dialog-behavior/paper-dialog-shared-styles.html" + type="chrome_html" /> <structure name="IDR_POLYMER_1_0_PAPER_DIALOG_PAPER_DIALOG_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/paper-dialog/paper-dialog-extracted.js" type="chrome_html" /> @@ -485,6 +488,12 @@ <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ICON_ITEM_HTML" file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-icon-item.html" type="chrome_html" /> + <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_BEHAVIOR_EXTRACTED_JS" + file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior-extracted.js" + type="chrome_html" /> + <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_BEHAVIOR_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior.html" + type="chrome_html" /> <structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_BODY_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-body-extracted.js" type="chrome_html" /> @@ -521,8 +530,8 @@ <structure name="IDR_POLYMER_1_0_PAPER_MENU_PAPER_MENU_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-extracted.js" type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_PAPER_MENU_PAPER_MENU_SHARED_CSS" - file="../../../third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared.css" + <structure name="IDR_POLYMER_1_0_PAPER_MENU_PAPER_MENU_SHARED_STYLES_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-shared-styles.html" type="chrome_html" /> <structure name="IDR_POLYMER_1_0_PAPER_MENU_PAPER_MENU_HTML" file="../../../third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu.html" @@ -566,12 +575,12 @@ <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-extracted.js" type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner.html" - type="chrome_html" /> <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_STYLES_HTML" file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-styles.html" type="chrome_html" /> + <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_HTML" + file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner.html" + type="chrome_html" /> <structure name="IDR_POLYMER_1_0_PAPER_STYLES_CLASSES_SHADOW_LAYOUT_HTML" file="../../../third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html" type="chrome_html" /> @@ -654,3 +663,4 @@ file="../../../third_party/web-animations-js/sources/web-animations-next-lite.min.js" type="chrome_html" /> </grit-part> +
diff --git a/ui/wm/core/transient_window_manager.cc b/ui/wm/core/transient_window_manager.cc index 2ca145d..f9d723f 100644 --- a/ui/wm/core/transient_window_manager.cc +++ b/ui/wm/core/transient_window_manager.cc
@@ -11,6 +11,7 @@ #include "base/stl_util.h" #include "ui/aura/window.h" #include "ui/aura/window_property.h" +#include "ui/aura/window_tracker.h" #include "ui/wm/core/transient_window_observer.h" #include "ui/wm/core/transient_window_stacking_client.h" #include "ui/wm/core/window_util.h" @@ -162,8 +163,17 @@ // If the window has transient children, updates the transient children's // visiblity as well. + // WindowTracker is used because child window + // could be deleted inside UpdateTransientChildVisibility call. + aura::WindowTracker tracker; for (Window* child : transient_children_) - Get(child)->UpdateTransientChildVisibility(visible); + tracker.Add(child); + + while (!tracker.windows().empty()) { + Window* window = *(tracker.windows().begin()); + Get(window)->UpdateTransientChildVisibility(visible); + tracker.Remove(window); + } // Remember the show request in |show_on_parent_visible_| and hide it again // if the following conditions are met
diff --git a/ui/wm/core/transient_window_manager_unittest.cc b/ui/wm/core/transient_window_manager_unittest.cc index bbc3820c..21553720 100644 --- a/ui/wm/core/transient_window_manager_unittest.cc +++ b/ui/wm/core/transient_window_manager_unittest.cc
@@ -8,6 +8,7 @@ #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" +#include "ui/aura/window_observer.h" #include "ui/wm/core/transient_window_observer.h" #include "ui/wm/core/window_util.h" #include "ui/wm/core/wm_state.h" @@ -44,6 +45,27 @@ DISALLOW_COPY_AND_ASSIGN(TestTransientWindowObserver); }; +class WindowVisibilityObserver : public aura::WindowObserver { + public: + WindowVisibilityObserver(Window* observed_window, + scoped_ptr<Window> owned_window) + : observed_window_(observed_window), owned_window_(owned_window.Pass()) { + observed_window_->AddObserver(this); + } + ~WindowVisibilityObserver() override { + observed_window_->RemoveObserver(this); + } + + void OnWindowVisibilityChanged(Window* window, bool visible) override { + owned_window_.reset(); + } + private: + Window* observed_window_; + scoped_ptr<Window> owned_window_; + + DISALLOW_COPY_AND_ASSIGN(WindowVisibilityObserver); +}; + class TransientWindowManagerTest : public aura::test::AuraTestBase { public: TransientWindowManagerTest() {} @@ -312,6 +334,17 @@ EXPECT_EQ("0 2 1", ChildWindowIDsAsString(root_window())); } +// Tests for a crash when window destroyed inside +// UpdateTransientChildVisibility loop. +TEST_F(TransientWindowManagerTest, CrashOnVisibilityChange) { + scoped_ptr<Window> window1(CreateTransientChild(1, root_window())); + scoped_ptr<Window> window2(CreateTransientChild(2, root_window())); + window1->Show(); + window2->Show(); + + WindowVisibilityObserver visibility_observer(window1.get(), window2.Pass()); + root_window()->Hide(); +} // Tests that windows are restacked properly after a call to AddTransientChild() // or RemoveTransientChild(). TEST_F(TransientWindowManagerTest, RestackUponAddOrRemoveTransientChild) {
diff --git a/win8/BUILD.gn b/win8/BUILD.gn index 1d4343d..fb43d2d 100644 --- a/win8/BUILD.gn +++ b/win8/BUILD.gn
@@ -10,29 +10,24 @@ } component("metro_viewer") { + sources = [ + "viewer/metro_viewer_process_host.cc", + "viewer/metro_viewer_process_host.h", + ] + + defines = [ "METRO_VIEWER_IMPLEMENTATION" ] + deps = [ ":metro_viewer_constants", "//base", "//ipc", "//ui/aura", + "//ui/gfx", "//ui/metro_viewer", ] - sources = [ - "viewer/metro_viewer_process_host.cc", - "viewer/metro_viewer_process_host.h", - ] - defines = [ "METRO_VIEWER_IMPLEMENTATION" ] } source_set("test_support_win8") { - deps = [ - ":test_registrar_constants", - "//base", - ] - - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - sources = [ "test/open_with_dialog_async.cc", "test/open_with_dialog_async.h", @@ -41,6 +36,14 @@ "test/ui_automation_client.cc", "test/ui_automation_client.h", ] + + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + + deps = [ + ":test_registrar_constants", + "//base", + ] } source_set("test_registrar_constants") { @@ -51,6 +54,16 @@ } executable("test_registrar") { + sources = [ + "test/test_registrar.cc", + "test/test_registrar.rc", + "test/test_registrar.rgs", + "test/test_registrar_resource.h", + ] + + configs -= [ "//build/config/win:console" ] + configs += [ "//build/config/win:windowed" ] + deps = [ ":test_registrar_constants", "//base", @@ -61,11 +74,4 @@ # process. "//chrome", ] - sources = [ - "test/test_registrar.cc", - "test/test_registrar.rc", - "test/test_registrar.rgs", - "test/test_registrar_resource.h", - ] - configs += [ "//build/config/win:windowed" ] }
diff --git a/win8/delegate_execute/BUILD.gn b/win8/delegate_execute/BUILD.gn new file mode 100644 index 0000000..87cc1b1 --- /dev/null +++ b/win8/delegate_execute/BUILD.gn
@@ -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. + +import("//build/config/chrome_build.gni") +import("//build/config/ui.gni") +import("//chrome/version.gni") +import("//testing/test.gni") + +executable("delegate_execute") { + sources = [ + "delegate_execute.cc", + "delegate_execute.rc", + ] + + configs -= [ "//build/config/win:console" ] + configs += [ "//build/config/win:windowed" ] + + deps = [ + ":lib", + ":version_resources", + ] +} + +source_set("lib") { + visibility = [ ":*" ] + sources = [ + "chrome_util.cc", + "chrome_util.h", + "command_execute_impl.cc", + "command_execute_impl.h", + "command_execute_impl.rgs", + "crash_server_init.cc", + "crash_server_init.h", + "delegate_execute_operation.cc", + "delegate_execute_operation.h", + "delegate_execute_util.cc", + "delegate_execute_util.h", + "resource.h", + ] + + public_deps = [ + "//base", + "//breakpad:breakpad_handler", + "//chrome/common:constants", + "//chrome/installer/util", + "//ui/base", + "//ui/gfx", + "//ui/gfx/geometry", + ] + + if (use_aura) { + public_deps += [ "//win8:metro_viewer_constants" ] + } + + if (is_chrome_branded) { + public_deps += [ "//google_update" ] + } +} + +process_version("version_resources") { + visibility = [ ":*" ] + sources = [ + "delegate_execute_exe.ver", + ] + output = "$target_gen_dir/delegate_execute_exe.rc" + template_file = chrome_version_rc_template +} + +test("delegate_execute_unittests") { + sources = [ + "delegate_execute_util_unittest.cc", + ] + deps = [ + ":lib", + "//base/test:run_all_unittests", + "//testing/gtest", + ] +}
diff --git a/win8/delegate_execute/chrome_util.cc b/win8/delegate_execute/chrome_util.cc index 858a2ca..247bb58 100644 --- a/win8/delegate_execute/chrome_util.cc +++ b/win8/delegate_execute/chrome_util.cc
@@ -29,7 +29,7 @@ #include "chrome/installer/util/util_constants.h" #if defined(GOOGLE_CHROME_BUILD) -#include "google_update/google_update_idl.h" +#include "google_update/google_update_idl.h" // nogncheck #endif namespace {
diff --git a/win8/delegate_execute/delegate_execute.gyp b/win8/delegate_execute/delegate_execute.gyp index 7247e08..8dcd71f 100644 --- a/win8/delegate_execute/delegate_execute.gyp +++ b/win8/delegate_execute/delegate_execute.gyp
@@ -11,6 +11,7 @@ ], 'targets': [ { + # GN version: //win8/delegate_execute:version_resources 'target_name': 'delegate_execute_version_resources', 'type': 'none', 'conditions': [ @@ -36,13 +37,13 @@ ], }, { + # GN version: //win8/delegate_execute 'target_name': 'delegate_execute', 'type': 'executable', 'dependencies': [ '../../base/base.gyp:base', '../../breakpad/breakpad.gyp:breakpad_handler', '../../chrome/chrome.gyp:installer_util', - '../../content/content.gyp:content_common', '../../google_update/google_update.gyp:google_update', '../../ui/base/ui_base.gyp:ui_base', '../../ui/gfx/gfx.gyp:gfx', @@ -85,6 +86,7 @@ ], }, { + # GN version: //win8/delegate_execute:delegate_execute_unittests 'target_name': 'delegate_execute_unittests', 'type': 'executable', 'dependencies': [
diff --git a/win8/metro_driver/BUILD.gn b/win8/metro_driver/BUILD.gn new file mode 100644 index 0000000..519259e --- /dev/null +++ b/win8/metro_driver/BUILD.gn
@@ -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. + +import("//build/config/ui.gni") +import("//chrome/version.gni") +import("//testing/test.gni") + +shared_library("metro_driver") { + sources = [ + "display_properties.cc", + "display_properties.h", + "metro_driver.cc", + "metro_driver.h", + "metro_driver_win7.cc", + "stdafx.h", + "winrt_utils.cc", + "winrt_utils.h", + ] + + deps = [ + ":copy_resources", + ":version_resources", + "//base", + "//chrome/common:constants", + "//chrome/installer/util", + "//crypto", + "//ipc", + "//sandbox", + "//ui/events", + "//ui/gfx", + "//ui/gfx/geometry", + "//ui/metro_viewer", + "//url", + ] + + if (use_aura) { + sources += [ + "chrome_app_view_ash.cc", + "chrome_app_view_ash.h", + "direct3d_helper.cc", + "direct3d_helper.h", + "file_picker_ash.cc", + "file_picker_ash.h", + ] + + deps += [ + "//ui/events:gesture_detection", + "//win8:metro_viewer_constants", + "//win8/metro_driver/ime", + ] + } else { + sources = [ + "chrome_app_view.cc", + "chrome_app_view.h", + "chrome_url_launch_handler.cc", + "chrome_url_launch_handler.h", + "devices_handler.cc", + "devices_handler.h", + "file_picker.cc", + "file_picker.h", + "metro_dialog_box.cc", + "metro_dialog_box.h", + "print_document_source.cc", + "print_document_source.h", + "print_handler.cc", + "print_handler.h", + "secondary_tile.cc", + "secondary_tile.h", + "settings_handler.cc", + "settings_handler.h", + "toast_notification_handler.cc", + "toast_notification_handler.h", + ] + } + + libs = [ + "D2D1.lib", + "D3D11.lib", + "runtimeobject.lib", + ] + + ldflags = [ + "/DELAYLOAD:API-MS-WIN-CORE-WINRT-ERROR-L1-1-0.DLL", + "/DELAYLOAD:API-MS-WIN-CORE-WINRT-L1-1-0.DLL", + "/DELAYLOAD:API-MS-WIN-CORE-WINRT-STRING-L1-1-0.DLL", + ] +} + +process_version("version_resources") { + visibility = [ ":*" ] + sources = [ + "metro_driver_dll.ver", + ] + output = "$target_gen_dir/metro_driver_dll_version.rc" + template_file = chrome_version_rc_template +} + +copy("copy_resources") { + visibility = [ ":*" ] + + sources = [ + "resources/Logo.png", + "resources/SecondaryTile.png", + "resources/SmallLogo.png", + "resources/chrome.VisualElementsManifest.xml", + ] + + outputs = [ + "$root_out_dir/{{source_file_part}}", + ] +} + +test("metro_driver_unittests") { + sources = [ + "run_all_unittests.cc", + "winrt_utils.cc", + "winrt_utils.h", + "winrt_utils_unittest.cc", + ] + + deps = [ + ":metro_driver", + "//base", + "//chrome/installer/util", + "//testing/gtest", + ] +}
diff --git a/win8/metro_driver/ime/BUILD.gn b/win8/metro_driver/ime/BUILD.gn new file mode 100644 index 0000000..63ebd99 --- /dev/null +++ b/win8/metro_driver/ime/BUILD.gn
@@ -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. + +source_set("ime") { + visibility = [ "//win8/metro_driver/*" ] + sources = [ + "ime_popup_monitor.cc", + "ime_popup_monitor.h", + "ime_popup_observer.h", + "input_scope.cc", + "input_scope.h", + "input_source.cc", + "input_source.h", + "input_source_observer.h", + "text_service.cc", + "text_service.h", + "text_service_delegate.h", + "text_store.cc", + "text_store.h", + "text_store_delegate.h", + ] + + deps = [ + "//base", + "//ui/base", + "//ui/metro_viewer", + ] +}
diff --git a/win8/metro_driver/ime/ime.gypi b/win8/metro_driver/ime/ime.gypi index ba9db46..f5d489c 100644 --- a/win8/metro_driver/ime/ime.gypi +++ b/win8/metro_driver/ime/ime.gypi
@@ -3,6 +3,7 @@ # found in the LICENSE file. { + # GN version: //win8/metro_driver/ime 'sources': [ 'ime_popup_monitor.cc', 'ime_popup_monitor.h',
diff --git a/win8/metro_driver/metro_driver.gyp b/win8/metro_driver/metro_driver.gyp index c58ae33..caa5ab5 100644 --- a/win8/metro_driver/metro_driver.gyp +++ b/win8/metro_driver/metro_driver.gyp
@@ -29,6 +29,7 @@ }, 'targets': [ { + # GN version: //win8/metro_driver:version_resources 'target_name': 'metro_driver_version_resources', 'type': 'none', 'variables': { @@ -44,6 +45,7 @@ ], }, { + # GN version: //win8/metro_driver 'target_name': 'metro_driver', 'type': 'shared_library', 'dependencies': [ @@ -114,6 +116,7 @@ ], 'copies': [ { + # GN version: //win8/metro_viewer:copy_resources 'destination': '<(PRODUCT_DIR)', 'files': [ 'resources/Logo.png', @@ -125,6 +128,7 @@ ], }, { + # GN version: //win8/metro_driver:metro_driver_unittests 'target_name': 'metro_driver_unittests', 'type': 'executable', 'dependencies': [