diff --git a/BUILD.gn b/BUILD.gn index e2df773a..6eefc1b 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -101,6 +101,7 @@ "//chrome", "//chrome/installer/zucchini:zucchini", "//chrome/installer/zucchini:zucchini_unittests", + "//chrome/profiling:unit_tests", "//chrome/test:browser_tests", "//chrome/test:interactive_ui_tests", "//chrome/test:sync_integration_tests",
diff --git a/DEPS b/DEPS index 2ebfe06..351485ff 100644 --- a/DEPS +++ b/DEPS
@@ -40,7 +40,7 @@ # 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': '69fd008199989c5a5a96f992dcaa4089b63f490f', + 'skia_revision': '5eb8fc585e9b3c9ccc82b0921986e1020ddaff23', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '656df4e2fcc877c34809f6018ab30ba5ddd0d623', + 'catapult_revision': 'bd05965e45572ae06d1a7139759a85a3d9a1a27c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index 027a22c..9e1df3b44 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -24,8 +24,6 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "components/autofill/content/renderer/autofill_agent.h" -#include "components/autofill/content/renderer/password_autofill_agent.h" #include "components/printing/renderer/print_render_frame_helper.h" #include "components/safe_browsing/renderer/renderer_url_loader_throttle.h" #include "components/safe_browsing/renderer/websocket_sb_handshake_throttle.h" @@ -178,15 +176,6 @@ parent_frame->GetRoutingID(), render_frame->GetRoutingID())); } - registry_ = base::MakeUnique<service_manager::BinderRegistry>(); - - // TODO(sgurun) do not create a password autofill agent (change - // autofill agent to store a weakptr). - autofill::PasswordAutofillAgent* password_autofill_agent = - new autofill::PasswordAutofillAgent(render_frame, registry_.get()); - new autofill::AutofillAgent(render_frame, password_autofill_agent, nullptr, - registry_.get()); - #if BUILDFLAG(ENABLE_SPELLCHECK) new SpellCheckProvider(render_frame, spellcheck_.get()); #endif
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h index fa815b28..e4ff745 100644 --- a/android_webview/renderer/aw_content_renderer_client.h +++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -15,7 +15,6 @@ #include "components/spellcheck/spellcheck_build_features.h" #include "components/web_restrictions/interfaces/web_restrictions.mojom.h" #include "content/public/renderer/content_renderer_client.h" -#include "services/service_manager/public/cpp/binder_registry.h" #if BUILDFLAG(ENABLE_SPELLCHECK) class SpellCheck; @@ -81,8 +80,6 @@ std::unique_ptr<SpellCheck> spellcheck_; #endif - std::unique_ptr<service_manager::BinderRegistry> registry_; - DISALLOW_COPY_AND_ASSIGN(AwContentRendererClient); };
diff --git a/android_webview/renderer/aw_render_frame_ext.cc b/android_webview/renderer/aw_render_frame_ext.cc index 284399f..860e420 100644 --- a/android_webview/renderer/aw_render_frame_ext.cc +++ b/android_webview/renderer/aw_render_frame_ext.cc
@@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "android_webview/renderer/aw_render_frame_ext.h" + #include "android_webview/common/aw_hit_test_data.h" #include "android_webview/common/render_view_messages.h" -#include "android_webview/renderer/aw_render_frame_ext.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/content/renderer/autofill_agent.h" +#include "components/autofill/content/renderer/password_autofill_agent.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" @@ -137,11 +140,25 @@ AwRenderFrameExt::AwRenderFrameExt(content::RenderFrame* render_frame) : content::RenderFrameObserver(render_frame) { + registry_ = base::MakeUnique<service_manager::BinderRegistry>(); + + // TODO(sgurun) do not create a password autofill agent (change + // autofill agent to store a weakptr). + autofill::PasswordAutofillAgent* password_autofill_agent = + new autofill::PasswordAutofillAgent(render_frame, registry_.get()); + new autofill::AutofillAgent(render_frame, password_autofill_agent, nullptr, + registry_.get()); } AwRenderFrameExt::~AwRenderFrameExt() { } +void AwRenderFrameExt::OnInterfaceRequestForFrame( + const std::string& interface_name, + mojo::ScopedMessagePipeHandle* interface_pipe) { + registry_->TryBindInterface(interface_name, interface_pipe); +} + void AwRenderFrameExt::DidCommitProvisionalLoad( bool is_new_navigation, bool is_same_document_navigation) {
diff --git a/android_webview/renderer/aw_render_frame_ext.h b/android_webview/renderer/aw_render_frame_ext.h index 9fd50194..55d4b38 100644 --- a/android_webview/renderer/aw_render_frame_ext.h +++ b/android_webview/renderer/aw_render_frame_ext.h
@@ -7,6 +7,8 @@ #include "base/macros.h" #include "content/public/renderer/render_frame_observer.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" @@ -31,6 +33,9 @@ ~AwRenderFrameExt() override; // RenderFrameObserver: + void OnInterfaceRequestForFrame( + const std::string& interface_name, + mojo::ScopedMessagePipeHandle* interface_pipe) override; void DidCommitProvisionalLoad(bool is_new_navigation, bool is_same_document_navigation) override; @@ -57,11 +62,11 @@ url::Origin last_origin_; + std::unique_ptr<service_manager::BinderRegistry> registry_; + DISALLOW_COPY_AND_ASSIGN(AwRenderFrameExt); }; } // namespace android_webview #endif // ANDROID_WEBVIEW_RENDERER_AW_RENDER_FRAME_EXT_H_ - -
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc index 36d0b0d..91f0f437 100644 --- a/ash/system/network/network_icon.cc +++ b/ash/system/network/network_icon.cc
@@ -884,8 +884,6 @@ if (!mobile_networks.empty()) return 0; - // TODO(lesliewatkins): Only return this message when Tether is uninitialized - // due to no Bluetooth (dependent on codereview.chromium.org/2969493002/). if (handler->GetTechnologyState(NetworkTypePattern::Tether()) == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) { s_uninitialized_msg = IDS_ASH_STATUS_TRAY_ENABLE_BLUETOOTH;
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc index 147e7aa..a0418c8c 100644 --- a/ash/system/network/network_list.cc +++ b/ash/system/network/network_list.cc
@@ -118,6 +118,11 @@ toggle_->SetIsOn(enabled, true); } + void SetToggleVisible(bool visible) { + toggle_->SetVisible(visible); + toggle_->set_accepts_events(visible); + } + protected: // This is called before the toggle button is added to give subclasses an // opportunity to add more buttons before the toggle button. Subclasses can @@ -460,17 +465,6 @@ UpdateNetworkChildren(NetworkInfo::Type::UNKNOWN, index); index += new_guids->size(); - if (handler->IsTechnologyAvailable(NetworkTypePattern::Cellular()) || - handler->IsTechnologyAvailable(NetworkTypePattern::Tether())) { - bool is_enabled = - handler->IsTechnologyEnabled(NetworkTypePattern::Cellular()) || - handler->IsTechnologyEnabled(NetworkTypePattern::Tether()); - - index = UpdateSectionHeaderRow(NetworkTypePattern::Cellular(), is_enabled, - index, &mobile_header_view_, - &mobile_separator_view_); - } - // Cellular initializing. int cellular_message_id = network_icon::GetMobileUninitializedMsg(); if (!cellular_message_id && @@ -478,6 +472,23 @@ !handler->FirstNetworkByType(NetworkTypePattern::Mobile())) { cellular_message_id = IDS_ASH_STATUS_TRAY_NO_MOBILE_NETWORKS; } + + if (handler->IsTechnologyAvailable(NetworkTypePattern::Cellular()) || + handler->IsTechnologyAvailable(NetworkTypePattern::Tether())) { + bool is_enabled = + handler->IsTechnologyEnabled(NetworkTypePattern::Cellular()) || + handler->IsTechnologyEnabled(NetworkTypePattern::Tether()); + + // The toggle is not visible in the case when Bluetooth must be + // enabled in order to enable Tether. + bool toggle_is_visible = + cellular_message_id != IDS_ASH_STATUS_TRAY_ENABLE_BLUETOOTH; + + index = UpdateSectionHeaderRow( + NetworkTypePattern::Cellular(), is_enabled, toggle_is_visible, index, + &mobile_header_view_, &mobile_separator_view_); + } + UpdateInfoLabel(cellular_message_id, index, &no_mobile_networks_view_); if (cellular_message_id) ++index; @@ -490,8 +501,8 @@ index = UpdateSectionHeaderRow( NetworkTypePattern::WiFi(), - handler->IsTechnologyEnabled(NetworkTypePattern::WiFi()), index, - &wifi_header_view_, &wifi_separator_view_); + handler->IsTechnologyEnabled(NetworkTypePattern::WiFi()), + true /* show_toggle */, index, &wifi_header_view_, &wifi_separator_view_); // "Wifi Enabled / Disabled". int wifi_message_id = 0; @@ -662,6 +673,7 @@ int NetworkListView::UpdateSectionHeaderRow(NetworkTypePattern pattern, bool enabled, + bool show_toggle, int child_index, SectionHeaderRowView** view, views::Separator** separator_view) { @@ -687,6 +699,7 @@ } (*view)->SetIsOn(enabled); + (*view)->SetToggleVisible(show_toggle); PlaceViewAtIndex(*view, child_index++); return child_index; }
diff --git a/ash/system/network/network_list.h b/ash/system/network/network_list.h index 09b18a4..1ebe4c22 100644 --- a/ash/system/network/network_list.h +++ b/ash/system/network/network_list.h
@@ -114,6 +114,7 @@ // be inserted, i.e., the index directly after the last inserted child. int UpdateSectionHeaderRow(chromeos::NetworkTypePattern pattern, bool enabled, + bool show_toggle, int child_index, SectionHeaderRowView** view, views::Separator** separator_view);
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 19891b8b..7780df528 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc
@@ -545,21 +545,24 @@ bool Histogram::ValidateHistogramContents(bool crash_if_invalid, int corrupted_count) const { enum Fields : int { - kBucketRangesField, + kUnloggedBucketRangesField, kUnloggedSamplesField, kLoggedSamplesField, kIdField, kHistogramNameField, kFlagsField, + kLoggedBucketRangesField, }; uint32_t bad_fields = 0; if (!unlogged_samples_) bad_fields |= 1 << kUnloggedSamplesField; - else if (!bucket_ranges()) - bad_fields |= 1 << kBucketRangesField; + else if (!unlogged_samples_->bucket_ranges()) + bad_fields |= 1 << kUnloggedBucketRangesField; if (!logged_samples_) bad_fields |= 1 << kLoggedSamplesField; + else if (!logged_samples_->bucket_ranges()) + bad_fields |= 1 << kLoggedBucketRangesField; else if (logged_samples_->id() == 0) bad_fields |= 1 << kIdField; else if (HashMetricName(histogram_name()) != logged_samples_->id())
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc index e36999a..130fd19 100644 --- a/base/threading/sequenced_worker_pool.cc +++ b/base/threading/sequenced_worker_pool.cc
@@ -366,8 +366,6 @@ void Shutdown(int max_blocking_tasks_after_shutdown); - bool IsShutdownInProgress(); - // Runs the worker loop on the background thread. void ThreadLoop(Worker* this_worker); @@ -967,11 +965,6 @@ #endif } -bool SequencedWorkerPool::Inner::IsShutdownInProgress() { - AutoLock lock(lock_); - return shutdown_called_; -} - void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) { DCHECK_EQ(AllPoolsState::USE_WORKER_POOL, g_all_pools_state); { @@ -1623,10 +1616,6 @@ inner_->Shutdown(max_new_blocking_tasks_after_shutdown); } -bool SequencedWorkerPool::IsShutdownInProgress() { - return inner_->IsShutdownInProgress(); -} - bool SequencedWorkerPool::IsRunningSequenceOnCurrentThread( SequenceToken sequence_token) const { return inner_->IsRunningSequenceOnCurrentThread(sequence_token);
diff --git a/base/threading/sequenced_worker_pool.h b/base/threading/sequenced_worker_pool.h index d95d7f2..005b4867 100644 --- a/base/threading/sequenced_worker_pool.h +++ b/base/threading/sequenced_worker_pool.h
@@ -365,12 +365,6 @@ // Must be called from the same thread this object was constructed on. void Shutdown(int max_new_blocking_tasks_after_shutdown); - // Check if Shutdown was called for given threading pool. This method is used - // for aborting time consuming operation to avoid blocking shutdown. - // - // Can be called from any thread. - bool IsShutdownInProgress(); - protected: ~SequencedWorkerPool() override;
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py index cc47f5dc9..0ba1b4c 100755 --- a/build/fuchsia/test_runner.py +++ b/build/fuchsia/test_runner.py
@@ -183,6 +183,8 @@ # that to align it properly after the frame index. addr2line_filtered = addr2line_output.strip().replace( '(inlined', ' ' * len(prefix) + '(inlined') + if '??' in addr2line_filtered: + addr2line_filtered = "%s+%s" % (os.path.basename(entry[1]), entry[2]) return '%s%s' % (prefix, addr2line_filtered) @@ -345,9 +347,10 @@ line = qemu_popen.stdout.readline().strip() if not line: break - print line if 'SUCCESS: all tests passed.' in line: success = True + + # Check for an end-of-backtrace marker. if bt_end_re.match(line): if bt_entries: print '----- start symbolized stack' @@ -355,18 +358,24 @@ print processed print '----- end symbolized stack' bt_entries = [] - else: - # Try to parse this as a Fuchsia system backtrace. - m = bt_with_offset_re.match(line) - if m: - bt_entries.append((m.group(1), args.test_name, m.group(4))) - continue + continue - # Try to parse the line as an in-process backtrace entry. - m = in_process_re.match(line) - if m: - bt_entries.append((m.group(1), args.test_name, m.group(2))) - continue + # Try to parse this as a Fuchsia system backtrace. + m = bt_with_offset_re.match(line) + if m: + bt_entries.append((m.group(1), args.test_name, m.group(4))) + continue + + # Try to parse the line as an in-process backtrace entry. + m = in_process_re.match(line) + if m: + bt_entries.append((m.group(1), args.test_name, m.group(2))) + continue + + # Some other line, so print it. Back-traces should not be interleaved with + # other output, so while this may re-order lines we see, it should actually + # make things more readable. + print line qemu_popen.wait()
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h index 57ee5a1..b21d0a6 100644 --- a/cc/paint/paint_canvas.h +++ b/cc/paint/paint_canvas.h
@@ -115,10 +115,6 @@ virtual void drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) = 0; - virtual void drawCircle(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) = 0; virtual void drawArc(const SkRect& oval, SkScalar start_angle, SkScalar sweep_angle,
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 16175bb..3bc927a 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -183,7 +183,6 @@ M(ClipRRectOp) \ M(ConcatOp) \ M(DrawArcOp) \ - M(DrawCircleOp) \ M(DrawColorOp) \ M(DrawDRRectOp) \ M(DrawImageOp) \ @@ -354,8 +353,6 @@ return "Concat"; case PaintOpType::DrawArc: return "DrawArc"; - case PaintOpType::DrawCircle: - return "DrawCircle"; case PaintOpType::DrawColor: return "DrawColor"; case PaintOpType::DrawDRRect: @@ -480,19 +477,6 @@ return helper.size(); } -size_t DrawCircleOp::Serialize(const PaintOp* base_op, - void* memory, - size_t size, - const SerializeOptions& options) { - auto* op = static_cast<const DrawCircleOp*>(base_op); - PaintOpWriter helper(memory, size); - helper.Write(op->flags); - helper.Write(op->cx); - helper.Write(op->cy); - helper.Write(op->radius); - return helper.size(); -} - size_t DrawColorOp::Serialize(const PaintOp* op, void* memory, size_t size, @@ -816,26 +800,6 @@ return op; } -PaintOp* DrawCircleOp::Deserialize(const void* input, - size_t input_size, - void* output, - size_t output_size) { - DCHECK_GE(output_size, sizeof(DrawCircleOp)); - DrawCircleOp* op = new (output) DrawCircleOp; - - PaintOpReader helper(input, input_size); - helper.Read(&op->flags); - helper.Read(&op->cx); - helper.Read(&op->cy); - helper.Read(&op->radius); - if (!helper.valid() || !op->IsValid()) { - op->~DrawCircleOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; -} - PaintOp* DrawColorOp::Deserialize(const void* input, size_t input_size, void* output, @@ -1189,14 +1153,6 @@ paint); } -void DrawCircleOp::RasterWithFlags(const DrawCircleOp* op, - const PaintFlags* flags, - SkCanvas* canvas, - const PlaybackParams& params) { - SkPaint paint = flags->ToSkPaint(); - canvas->drawCircle(op->cx, op->cy, op->radius, paint); -} - void DrawColorOp::Raster(const DrawColorOp* op, SkCanvas* canvas, const PlaybackParams& params) { @@ -1486,14 +1442,6 @@ rect->sort(); return true; } - case PaintOpType::DrawCircle: { - auto* circle_op = static_cast<const DrawCircleOp*>(op); - *rect = SkRect::MakeXYWH(circle_op->cx - circle_op->radius, - circle_op->cy - circle_op->radius, - 2 * circle_op->radius, 2 * circle_op->radius); - rect->sort(); - return true; - } case PaintOpType::DrawColor: return false; case PaintOpType::DrawDRRect: {
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index fb3a773..4e545d8 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -63,7 +63,6 @@ ClipRRect, Concat, DrawArc, - DrawCircle, DrawColor, DrawDRRect, DrawImage, @@ -367,30 +366,6 @@ DrawArcOp() = default; }; -class CC_PAINT_EXPORT DrawCircleOp final : public PaintOpWithFlags { - public: - static constexpr PaintOpType kType = PaintOpType::DrawCircle; - static constexpr bool kIsDrawOp = true; - DrawCircleOp(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) - : PaintOpWithFlags(flags), cx(cx), cy(cy), radius(radius) {} - static void RasterWithFlags(const DrawCircleOp* op, - const PaintFlags* flags, - SkCanvas* canvas, - const PlaybackParams& params); - bool IsValid() const { return flags.IsValid(); } - HAS_SERIALIZATION_FUNCTIONS(); - - SkScalar cx; - SkScalar cy; - SkScalar radius; - - private: - DrawCircleOp() = default; -}; - class CC_PAINT_EXPORT DrawColorOp final : public PaintOp { public: static constexpr PaintOpType kType = PaintOpType::DrawColor;
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 8a91197..2c4ead41 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -1663,14 +1663,6 @@ } } -void PushDrawCircleOps(PaintOpBuffer* buffer) { - size_t len = std::min(test_floats.size() - 2, test_flags.size()); - for (size_t i = 0; i < len; ++i) { - buffer->push<DrawCircleOp>(test_floats[i], test_floats[i + 1], - test_floats[i + 2], test_flags[i]); - } -} - void PushDrawColorOps(PaintOpBuffer* buffer) { for (size_t i = 0; i < test_colors.size(); ++i) { buffer->push<DrawColorOp>(test_colors[i], static_cast<SkBlendMode>(i)); @@ -1896,16 +1888,6 @@ EXPECT_EQ(original->use_center, written->use_center); } -void CompareDrawCircleOp(const DrawCircleOp* original, - const DrawCircleOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->cx, written->cx); - EXPECT_EQ(original->cy, written->cy); - EXPECT_EQ(original->radius, written->radius); -} - void CompareDrawColorOp(const DrawColorOp* original, const DrawColorOp* written) { EXPECT_TRUE(original->IsValid()); @@ -2124,9 +2106,6 @@ case PaintOpType::DrawArc: PushDrawArcOps(&buffer_); break; - case PaintOpType::DrawCircle: - PushDrawCircleOps(&buffer_); - break; case PaintOpType::DrawColor: PushDrawColorOps(&buffer_); break; @@ -2228,10 +2207,6 @@ CompareDrawArcOp(static_cast<const DrawArcOp*>(original), static_cast<const DrawArcOp*>(written)); break; - case PaintOpType::DrawCircle: - CompareDrawCircleOp(static_cast<const DrawCircleOp*>(original), - static_cast<const DrawCircleOp*>(written)); - break; case PaintOpType::DrawColor: CompareDrawColorOp(static_cast<const DrawColorOp*>(original), static_cast<const DrawColorOp*>(written)); @@ -2705,27 +2680,6 @@ } } -TEST(PaintOpBufferTest, BoundingRect_DrawCircleOp) { - PaintOpBuffer buffer; - PaintFlags flags; - buffer.push<DrawCircleOp>(0.f, 0.f, 5.f, flags); - buffer.push<DrawCircleOp>(-1.f, 4.f, 44.f, flags); - buffer.push<DrawCircleOp>(-99.f, -32.f, 100.f, flags); - - SkRect rect; - for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) { - auto* op = static_cast<DrawCircleOp*>(base_op); - - SkScalar dimension = 2 * op->radius; - SkScalar x = op->cx - op->radius; - SkScalar y = op->cy - op->radius; - SkRect circle_rect = SkRect::MakeXYWH(x, y, dimension, dimension); - - ASSERT_TRUE(PaintOp::GetBounds(op, &rect)); - EXPECT_EQ(rect, circle_rect.makeSorted()); - } -} - TEST(PaintOpBufferTest, BoundingRect_DrawImageOp) { PaintOpBuffer buffer; PushDrawImageOps(&buffer);
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc index aaa02a9e..8b43504 100644 --- a/cc/paint/record_paint_canvas.cc +++ b/cc/paint/record_paint_canvas.cc
@@ -241,13 +241,6 @@ list_->push<DrawDRRectOp>(outer, inner, flags); } -void RecordPaintCanvas::drawCircle(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) { - list_->push<DrawCircleOp>(cx, cy, radius, flags); -} - void RecordPaintCanvas::drawArc(const SkRect& oval, SkScalar start_angle, SkScalar sweep_angle,
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h index de10644..6d72986 100644 --- a/cc/paint/record_paint_canvas.h +++ b/cc/paint/record_paint_canvas.h
@@ -74,10 +74,6 @@ void drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) override; - void drawCircle(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) override; void drawArc(const SkRect& oval, SkScalar start_angle, SkScalar sweep_angle,
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc index 967ea16..2f1904f 100644 --- a/cc/paint/skia_paint_canvas.cc +++ b/cc/paint/skia_paint_canvas.cc
@@ -203,14 +203,6 @@ canvas_->drawDRRect(outer, inner, paint); } -void SkiaPaintCanvas::drawCircle(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) { - SkPaint paint = flags.ToSkPaint(); - canvas_->drawCircle(cx, cy, radius, paint); -} - void SkiaPaintCanvas::drawArc(const SkRect& oval, SkScalar start_angle, SkScalar sweep_angle,
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h index 6ce174b..2777f1e 100644 --- a/cc/paint/skia_paint_canvas.h +++ b/cc/paint/skia_paint_canvas.h
@@ -82,10 +82,6 @@ void drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) override; - void drawCircle(SkScalar cx, - SkScalar cy, - SkScalar radius, - const PaintFlags& flags) override; void drawArc(const SkRect& oval, SkScalar start_angle, SkScalar sweep_angle,
diff --git a/cc/paint/solid_color_analyzer.cc b/cc/paint/solid_color_analyzer.cc index 7b556e0..510f73b 100644 --- a/cc/paint/solid_color_analyzer.cc +++ b/cc/paint/solid_color_analyzer.cc
@@ -198,7 +198,6 @@ // Any of the following ops result in non solid content. case PaintOpType::DrawArc: - case PaintOpType::DrawCircle: case PaintOpType::DrawDRRect: case PaintOpType::DrawImage: case PaintOpType::DrawImageRect:
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 78865db..10b3be3 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -967,7 +967,11 @@ SetNeedsCommit(); } -void LayerTreeHost::SetViewportSize(const gfx::Size& device_viewport_size) { +void LayerTreeHost::SetViewportSize( + const gfx::Size& device_viewport_size, + const viz::LocalSurfaceId& local_surface_id) { + if (settings_.enable_surface_synchronization) + SetLocalSurfaceId(local_surface_id); if (device_viewport_size_ == device_viewport_size) return;
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index a68f671..2b5f0aca 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -285,7 +285,9 @@ return event_listener_properties_[static_cast<size_t>(event_class)]; } - void SetViewportSize(const gfx::Size& device_viewport_size); + void SetViewportSize( + const gfx::Size& device_viewport_size, + const viz::LocalSurfaceId& local_surface_id = viz::LocalSurfaceId()); gfx::Size device_viewport_size() const { return device_viewport_size_; } void SetBrowserControlsHeight(float top_height,
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc index efb1d16..ee78966 100644 --- a/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -247,10 +247,13 @@ PaintFlags flags; flags.setStyle(PaintFlags::kFill_Style); flags.setColor(SK_ColorWHITE); - display_list->push<DrawCircleOp>(bounds_.width() / 2.f, - bounds_.height() / 2.f, - bounds_.width() / 4.f, flags); - + float radius = bounds_.width() / 4.f; + float circle_x = bounds_.width() / 2.f; + float circle_y = bounds_.height() / 2.f; + display_list->push<DrawOvalOp>( + SkRect::MakeLTRB(circle_x - radius, circle_y - radius, + circle_x + radius, circle_y + radius), + flags); display_list->push<RestoreOp>(); display_list->EndPaintOfUnpaired(PaintableRegion()); display_list->Finalize();
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 81e6527..3270fca 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -3010,21 +3010,23 @@ } void WillBeginMainFrame() override { - EXPECT_TRUE(allow_commits_); + EXPECT_TRUE(IsCommitAllowed()); num_send_begin_main_frame_++; EndTest(); } - void AllowCommits() { - allow_commits_ = true; - layer_tree_host()->SetDeferCommits(false); - } - void AfterTest() override { EXPECT_GE(num_will_begin_impl_frame_, 5); EXPECT_EQ(1, num_send_begin_main_frame_); } + virtual void AllowCommits() { + allow_commits_ = true; + layer_tree_host()->SetDeferCommits(false); + } + + virtual bool IsCommitAllowed() const { return allow_commits_; } + private: bool allow_commits_ = false; int num_will_begin_impl_frame_ = 0; @@ -3033,6 +3035,37 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeferCommits); +// This verifies that changing the size of a LayerTreeHost without providing a +// LocalSurfaceId defers commits. +class LayerTreeHostInvalidLocalSurfaceIdDefersCommit + : public LayerTreeHostTestDeferCommits { + public: + LayerTreeHostInvalidLocalSurfaceIdDefersCommit() = default; + void InitializeSettings(LayerTreeSettings* settings) override { + // With surface synchronization turned on, commits are deferred until a + // LocalSurfaceId has been assigned. The set up code sets the size of the + // LayerTreeHost (using SetViewportSize()), without providing a + // LocalSurfaceId. So, commits should be deferred until we set an id later + // during the test (in AllowCommits() override below). + settings->enable_surface_synchronization = true; + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void AllowCommits() override { + local_surface_id_ = allocator_.GenerateId(); + PostSetLocalSurfaceIdToMainThread(local_surface_id_); + } + + bool IsCommitAllowed() const override { return local_surface_id_.is_valid(); } + + private: + viz::LocalSurfaceIdAllocator allocator_; + viz::LocalSurfaceId local_surface_id_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostInvalidLocalSurfaceIdDefersCommit); + // This verifies that we can abort a commit inside the main frame, and // we don't leave any weird states around if we never allow the commit // to happen.
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 48efa8e..e56a06b 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1551,7 +1551,6 @@ "//chrome/browser/resources:invalidations_resources", "//chrome/browser/resources:net_internals_resources", "//chrome/browser/resources:password_manager_internals_resources", - "//chrome/browser/resources:policy_resources", "//chrome/browser/resources:quota_internals_resources", "//chrome/browser/resources:task_scheduler_internals_resources", "//chrome/browser/resources:translate_internals_resources",
diff --git a/chrome/VERSION b/chrome/VERSION index ba0767f..e1da9206 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=62 MINOR=0 -BUILD=3181 +BUILD=3182 PATCH=0
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0844a81..f22f77e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1963,10 +1963,6 @@ switches::kEnableMessageCenterNewStyleNotification, switches::kDisableMessageCenterNewStyleNotification)}, #endif // !OS_ANDROID - {"enable-md-policy-page", - flag_descriptions::kEnableMaterialDesignPolicyPageName, - flag_descriptions::kEnableMaterialDesignPolicyPageDescription, kOsDesktop, - SINGLE_VALUE_TYPE(switches::kEnableMaterialDesignPolicyPage)}, #if defined(OS_CHROMEOS) {"memory-pressure-thresholds", flag_descriptions::kMemoryPressureThresholdName,
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 8144ff5..82a50e4 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -384,6 +384,7 @@ #endif #if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) +#include "chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.h" #include "chrome/browser/profiling_host/profiling_process_host.h" #include "chrome/common/profiling/constants.mojom.h" #endif @@ -910,6 +911,10 @@ main_parts->AddParts(new ChromeBrowserMainExtraPartsX11()); #endif +#if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) + main_parts->AddParts(new ChromeBrowserMainExtraPartsProfiling); +#endif + chrome::AddMetricsExtraParts(main_parts); return main_parts; @@ -1567,17 +1572,11 @@ *base::CommandLine::ForCurrentProcess(); static const char* const kCommonSwitchNames[] = { -#if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) - switches::kMemlogPipe, -#endif switches::kUserAgent, switches::kUserDataDir, // Make logs go to the right file. }; command_line->CopySwitchesFrom(browser_command_line, kCommonSwitchNames, arraysize(kCommonSwitchNames)); -#if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) - profiling::ProfilingProcessHost::AddSwitchesToChildCmdLine(command_line); -#endif static const char* const kDinosaurEasterEggSwitches[] = { error_page::switches::kDisableDinosaurEasterEgg,
diff --git a/chrome/browser/chrome_content_gpu_manifest_overlay.json b/chrome/browser/chrome_content_gpu_manifest_overlay.json index a0e50fa2..b382337 100644 --- a/chrome/browser/chrome_content_gpu_manifest_overlay.json +++ b/chrome/browser/chrome_content_gpu_manifest_overlay.json
@@ -8,12 +8,8 @@ "arc::mojom::VideoDecodeClient", "arc::mojom::VideoEncodeAccelerator", "arc::mojom::VideoEncodeClient", - "chrome::mojom::ResourceUsageReporter" - ] - }, - "requires": { - "profiling": [ - "memlog" + "chrome::mojom::ResourceUsageReporter", + "profiling::mojom::MemlogClient" ] } }
diff --git a/chrome/browser/chrome_content_renderer_manifest_overlay.json b/chrome/browser/chrome_content_renderer_manifest_overlay.json index eee27d1..9179941 100644 --- a/chrome/browser/chrome_content_renderer_manifest_overlay.json +++ b/chrome/browser/chrome_content_renderer_manifest_overlay.json
@@ -6,12 +6,8 @@ "browser": [ "chrome::mojom::ResourceUsageReporter", "chrome::mojom::SearchBouncer", - "spellcheck::mojom::SpellChecker" - ] - }, - "requires": { - "profiling": [ - "memlog" + "spellcheck::mojom::SpellChecker", + "profiling::mojom::MemlogClient" ] } },
diff --git a/chrome/browser/chrome_content_utility_manifest_overlay.json b/chrome/browser/chrome_content_utility_manifest_overlay.json index df19464..07008f85 100644 --- a/chrome/browser/chrome_content_utility_manifest_overlay.json +++ b/chrome/browser/chrome_content_utility_manifest_overlay.json
@@ -18,6 +18,7 @@ "extensions::mojom::WiFiCredentialsGetter", "net::interfaces::ProxyResolverFactory", "payments::mojom::PaymentManifestParser", + "profiling::mojom::MemlogClient", "safe_json::mojom::SafeJsonParser" ] }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index d42e4550..08e5b09 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1871,6 +1871,7 @@ "policy/user_cloud_policy_store_chromeos_unittest.cc", "power/cpu_data_collector_unittest.cc", "power/extension_event_observer_unittest.cc", + "power/peripheral_battery_observer_unittest.cc", "power/power_data_collector_unittest.cc", "power/power_prefs_unittest.cc", "power/renderer_freezer_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc index 23829b795..fc3c9bc 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
@@ -223,6 +223,27 @@ callback); } +void ArcFileSystemOperationRunner::GetRecentDocuments( + const std::string& authority, + const std::string& root_id, + const GetRecentDocumentsCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (should_defer_) { + deferred_operations_.emplace_back(base::Bind( + &ArcFileSystemOperationRunner::GetRecentDocuments, + weak_ptr_factory_.GetWeakPtr(), authority, root_id, callback)); + return; + } + auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD( + arc_bridge_service_->file_system(), GetRecentDocuments); + if (!file_system_instance) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback, base::nullopt)); + return; + } + file_system_instance->GetRecentDocuments(authority, root_id, callback); +} + void ArcFileSystemOperationRunner::AddWatcher( const std::string& authority, const std::string& document_id,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h index 004408c..eadf57f7 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
@@ -70,6 +70,8 @@ using GetDocumentCallback = mojom::FileSystemInstance::GetDocumentCallback; using GetChildDocumentsCallback = mojom::FileSystemInstance::GetChildDocumentsCallback; + using GetRecentDocumentsCallback = + mojom::FileSystemInstance::GetRecentDocumentsCallback; using AddWatcherCallback = base::Callback<void(int64_t watcher_id)>; using RemoveWatcherCallback = base::Callback<void(bool success)>; using ChangeType = storage::WatcherManager::ChangeType; @@ -121,6 +123,9 @@ void GetChildDocuments(const std::string& authority, const std::string& parent_document_id, const GetChildDocumentsCallback& callback); + void GetRecentDocuments(const std::string& authority, + const std::string& root_id, + const GetRecentDocumentsCallback& callback); void AddWatcher(const std::string& authority, const std::string& document_id, const WatcherCallback& watcher_callback,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc index b47b88a1..830793f 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
@@ -92,6 +92,14 @@ ++*counter; }, counter)); + runner_->GetRecentDocuments( + kAuthority, kDocumentId, + base::Bind( + [](int* counter, + base::Optional<std::vector<mojom::DocumentPtr>> documents) { + ++*counter; + }, + counter)); runner_->OpenFileToRead( GURL(kUrl), base::Bind([](int* counter, mojo::ScopedHandle handle) { ++*counter; }, @@ -121,7 +129,7 @@ CallSetShouldDefer(false); CallAllFunctions(&counter); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(7, counter); + EXPECT_EQ(8, counter); } TEST_F(ArcFileSystemOperationRunnerTest, DeferAndRun) { @@ -133,7 +141,7 @@ CallSetShouldDefer(false); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(7, counter); + EXPECT_EQ(8, counter); } // TODO(nya,hidehiko): Check if we should keep this test. @@ -157,7 +165,7 @@ CallSetShouldDefer(false); CallAllFunctions(&counter); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(7, counter); + EXPECT_EQ(8, counter); } } // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc index 7a2d583..ccb9f56 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc
@@ -88,6 +88,20 @@ runner->GetChildDocuments(authority, parent_document_id, callback); } +void GetRecentDocumentsOnUIThread(const std::string& authority, + const std::string& root_id, + const GetRecentDocumentsCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto* runner = GetArcFileSystemOperationRunner(); + if (!runner) { + DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. " + << "File system operations are dropped."; + callback.Run(base::nullopt); + return; + } + runner->GetRecentDocuments(authority, root_id, callback); +} + void AddWatcherOnUIThread(const std::string& authority, const std::string& document_id, const WatcherCallback& watcher_callback, @@ -209,6 +223,19 @@ callback))); } +void GetRecentDocumentsOnIOThread(const std::string& authority, + const std::string& root_id, + const GetRecentDocumentsCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce( + &GetRecentDocumentsOnUIThread, authority, root_id, + base::Bind( + &PostToIOThread<base::Optional<std::vector<mojom::DocumentPtr>>>, + callback))); +} + void AddWatcherOnIOThread(const std::string& authority, const std::string& document_id, const WatcherCallback& watcher_callback,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h index b21c3da..4268c2d5 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h
@@ -22,6 +22,8 @@ using GetDocumentCallback = ArcFileSystemOperationRunner::GetDocumentCallback; using GetChildDocumentsCallback = ArcFileSystemOperationRunner::GetChildDocumentsCallback; +using GetRecentDocumentsCallback = + ArcFileSystemOperationRunner::GetRecentDocumentsCallback; using AddWatcherCallback = ArcFileSystemOperationRunner::AddWatcherCallback; using RemoveWatcherCallback = ArcFileSystemOperationRunner::RemoveWatcherCallback; @@ -73,6 +75,9 @@ void GetChildDocumentsOnIOThread(const std::string& authority, const std::string& parent_document_id, const GetChildDocumentsCallback& callback); +void GetRecentDocumentsOnIOThread(const std::string& authority, + const std::string& root_id, + const GetRecentDocumentsCallback& callback); void AddWatcherOnIOThread(const std::string& authority, const std::string& document_id, const WatcherCallback& watcher_callback,
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index ba2c11e..a4aa225 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -107,6 +107,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/pref_names.h" +#include "chrome/grit/chromium_strings.h" #include "chromeos/audio/audio_devices_pref_handler_impl.h" #include "chromeos/audio/cras_audio_handler.h" #include "chromeos/cert_loader.h" @@ -169,10 +170,12 @@ #include "ui/base/ime/chromeos/ime_keyboard.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/chromeos/input_method_util.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/touch/touch_device.h" #include "ui/chromeos/events/event_rewriter_chromeos.h" #include "ui/chromeos/events/pref_names.h" #include "ui/events/event_utils.h" +#include "ui/message_center/message_center.h" #if BUILDFLAG(ENABLE_RLZ) #include "components/rlz/rlz_tracker.h" @@ -787,6 +790,11 @@ VLOG(1) << "Relaunching browser for user: " << account_id.Serialize() << " with hash: " << user_id_hash; } + + // Set product name ("Chrome OS" or "Chromium OS") to be used in context + // header of new-style notification. + message_center::MessageCenter::Get()->SetProductOSName( + l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME)); } class GuestLanguageSetCallbackData {
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc index 62afd988..54b6f10 100644 --- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc +++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/extensions/extension_assets_manager.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/common/pref_names.h" +#include "extensions/browser/extension_file_task_runner.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/install_flag.h" @@ -315,7 +316,7 @@ extensions::ExtensionSystem::Get(lock_screen_profile_) ->extension_service(); - lock_screen_service->GetFileTaskRunner()->PostTask( + extensions::GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::Bind( &InstallExtensionCopy, lock_profile_app, app->path(),
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc index eb0f234..22a1eb3 100644 --- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc
@@ -32,6 +32,7 @@ #include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/event_router.h" #include "extensions/browser/event_router_factory.h" +#include "extensions/browser/extension_file_task_runner.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/api/app_runtime.h" @@ -358,11 +359,8 @@ // file runner task finish, void RunExtensionServiceTaskRunner(Profile* profile) { base::RunLoop run_loop; - extensions::ExtensionSystem::Get(profile) - ->extension_service() - ->GetFileTaskRunner() - ->PostTaskAndReply(FROM_HERE, base::Bind(&base::DoNothing), - run_loop.QuitClosure()); + extensions::GetExtensionFileTaskRunner()->PostTaskAndReply( + FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure()); run_loop.Run(); }
diff --git a/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc b/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc index c2c06cb..ff776ec0 100644 --- a/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc +++ b/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc
@@ -81,6 +81,16 @@ IDR_LOGIN_DEFAULT_USER_45, IDR_LOGIN_DEFAULT_USER_46, IDR_LOGIN_DEFAULT_USER_47, + IDR_LOGIN_DEFAULT_USER_48, + IDR_LOGIN_DEFAULT_USER_49, + IDR_LOGIN_DEFAULT_USER_50, + IDR_LOGIN_DEFAULT_USER_51, + IDR_LOGIN_DEFAULT_USER_52, + IDR_LOGIN_DEFAULT_USER_53, + IDR_LOGIN_DEFAULT_USER_54, + IDR_LOGIN_DEFAULT_USER_55, + IDR_LOGIN_DEFAULT_USER_56, + IDR_LOGIN_DEFAULT_USER_57, }; const int kDefaultImagesCount = arraysize(kDefaultImageResourceIDs); @@ -230,6 +240,16 @@ IDS_LOGIN_DEFAULT_USER_DESC_45, IDS_LOGIN_DEFAULT_USER_DESC_46, IDS_LOGIN_DEFAULT_USER_DESC_47, + IDS_LOGIN_DEFAULT_USER_DESC_48, + IDS_LOGIN_DEFAULT_USER_DESC_49, + IDS_LOGIN_DEFAULT_USER_DESC_50, + IDS_LOGIN_DEFAULT_USER_DESC_51, + IDS_LOGIN_DEFAULT_USER_DESC_52, + IDS_LOGIN_DEFAULT_USER_DESC_53, + IDS_LOGIN_DEFAULT_USER_DESC_54, + IDS_LOGIN_DEFAULT_USER_DESC_55, + IDS_LOGIN_DEFAULT_USER_DESC_56, + IDS_LOGIN_DEFAULT_USER_DESC_57, }; const int kDefaultImageDescriptionsMaxID = arraysize(kDefaultImageDescriptions);
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer.cc b/chrome/browser/chromeos/power/peripheral_battery_observer.cc index 2d447b81..56a3611 100644 --- a/chrome/browser/chromeos/power/peripheral_battery_observer.cc +++ b/chrome/browser/chromeos/power/peripheral_battery_observer.cc
@@ -16,10 +16,6 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/notifications/notification.h" -#include "chrome/browser/notifications/notification_ui_manager.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/grit/theme_resources.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "content/public/browser/browser_thread.h" @@ -41,9 +37,9 @@ // it to be in low battery condition. const int kLowBatteryLevel = 15; -// Don't show 2 low battery notification within |kNotificationIntervalSec| -// seconds. -const int kNotificationIntervalSec = 60; +// Don't show 2 low battery notification within |kNotificationInterval|. +constexpr base::TimeDelta kNotificationInterval = + base::TimeDelta::FromSeconds(60); // TODO(sammiequon): Add a notification url to chrome://settings/stylus once // battery related information is shown there. @@ -93,22 +89,40 @@ return false; } -class PeripheralBatteryNotificationDelegate : public NotificationDelegate { - public: - explicit PeripheralBatteryNotificationDelegate(const std::string& id) - : id_(id) {} - - // Overridden from NotificationDelegate: - std::string id() const override { return id_; } - - private: - ~PeripheralBatteryNotificationDelegate() override {} - - const std::string id_; - - DISALLOW_COPY_AND_ASSIGN(PeripheralBatteryNotificationDelegate); +// Struct containing parameters for the notification which vary between the +// stylus notifications and the non stylus notifications. +struct NotificationParams { + std::string id; + base::string16 title; + base::string16 message; + int image_id; + std::string notifier_name; + GURL url; }; +NotificationParams GetNonStylusNotificationParams(const std::string& address, + const std::string& name, + int battery_level) { + return NotificationParams{ + address, + base::ASCIIToUTF16(name), + l10n_util::GetStringFUTF16Int( + IDS_ASH_LOW_PERIPHERAL_BATTERY_NOTIFICATION_TEXT, battery_level), + IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW, + kNotifierId, + GURL(kNotificationOriginUrl)}; +} + +NotificationParams GetStylusNotificationParams() { + return NotificationParams{ + PeripheralBatteryObserver::kStylusNotificationId, + l10n_util::GetStringUTF16(IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_TITLE), + l10n_util::GetStringUTF16(IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_BODY), + IDR_NOTIFICATION_STYLUS_BATTERY_LOW, + ash::system_notifier::kNotifierStylusBattery, + GURL()}; +} + } // namespace const char PeripheralBatteryObserver::kStylusNotificationId[] = @@ -116,7 +130,6 @@ PeripheralBatteryObserver::PeripheralBatteryObserver() : testing_clock_(NULL), - notification_profile_(NULL), weakptr_factory_( new base::WeakPtrFactory<PeripheralBatteryObserver>(this)) { DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); @@ -167,11 +180,13 @@ // below kLowBatteryLevel. // 2. The battery level is in record and it drops below kLowBatteryLevel. if (batteries_.find(address) == batteries_.end()) { - BatteryInfo battery{name, level, base::TimeTicks()}; + BatteryInfo battery{name, level, base::TimeTicks(), + IsStylusDevice(address, name)}; if (level <= kLowBatteryLevel) { - if (PostNotification(address, battery)) + if (PostNotification(address, battery)) { battery.last_notification_timestamp = testing_clock_ ? testing_clock_->NowTicks() : base::TimeTicks::Now(); + } } batteries_[address] = battery; } else { @@ -180,9 +195,10 @@ int old_level = battery->level; battery->level = level; if (old_level > kLowBatteryLevel && level <= kLowBatteryLevel) { - if (PostNotification(address, *battery)) + if (PostNotification(address, *battery)) { battery->last_notification_timestamp = testing_clock_ ? testing_clock_->NowTicks() : base::TimeTicks::Now(); + } } } } @@ -211,8 +227,8 @@ std::map<std::string, BatteryInfo>::iterator it = batteries_.find(address_lowercase); if (it != batteries_.end()) { - batteries_.erase(it); CancelNotification(address_lowercase); + batteries_.erase(it); } } @@ -223,71 +239,37 @@ // oscillates around the threshold level. base::TimeTicks now = testing_clock_ ? testing_clock_->NowTicks() : base::TimeTicks::Now(); - if (now - battery.last_notification_timestamp < - base::TimeDelta::FromSeconds(kNotificationIntervalSec)) + if (now - battery.last_notification_timestamp < kNotificationInterval) return false; - // Stylus battery notifications have a different icon and message. They are - // also system notifications. - // TODO(sammiequon): Change non-stylus notifications to also be system - // notifications. - if (IsStylusDevice(address, battery.name)) { - auto notification = base::MakeUnique<message_center::Notification>( - message_center::NOTIFICATION_TYPE_SIMPLE, kStylusNotificationId, - l10n_util::GetStringUTF16( - IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_TITLE), - l10n_util::GetStringUTF16(IDS_ASH_LOW_STYLUS_BATTERY_NOTIFICATION_BODY), - ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_NOTIFICATION_STYLUS_BATTERY_LOW), - base::string16(), GURL(), - message_center::NotifierId( - message_center::NotifierId::SYSTEM_COMPONENT, - ash::system_notifier::kNotifierStylusBattery), - message_center::RichNotificationData(), nullptr); - notification->SetSystemPriority(); + // Stylus battery notifications differ slightly. + NotificationParams params = battery.is_stylus + ? GetStylusNotificationParams() + : GetNonStylusNotificationParams( + address, battery.name, battery.level); - message_center::MessageCenter::Get()->AddNotification( - std::move(notification)); - return true; - } - - NotificationUIManager* notification_manager = - g_browser_process->notification_ui_manager(); - - base::string16 string_text = l10n_util::GetStringFUTF16Int( - IDS_ASH_LOW_PERIPHERAL_BATTERY_NOTIFICATION_TEXT, - battery.level); - - Notification notification( - message_center::NOTIFICATION_TYPE_SIMPLE, base::UTF8ToUTF16(battery.name), - string_text, ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW), + auto notification = base::MakeUnique<message_center::Notification>( + message_center::NOTIFICATION_TYPE_SIMPLE, params.id, params.title, + params.message, + ui::ResourceBundle::GetSharedInstance().GetImageNamed(params.image_id), + base::string16(), params.url, message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, - kNotifierId), - base::string16(), GURL(kNotificationOriginUrl), address, - message_center::RichNotificationData(), - new PeripheralBatteryNotificationDelegate(address)); + params.notifier_name), + message_center::RichNotificationData(), nullptr); + notification->SetSystemPriority(); - notification.set_priority(message_center::SYSTEM_PRIORITY); - - notification_profile_ = ProfileManager::GetPrimaryUserProfile(); - notification_manager->Add(notification, notification_profile_); - + message_center::MessageCenter::Get()->AddNotification( + std::move(notification)); return true; } void PeripheralBatteryObserver::CancelNotification(const std::string& address) { const auto it = batteries_.find(address); - if (it != batteries_.end() && IsStylusDevice(address, it->second.name)) { + if (it != batteries_.end()) { + std::string notification_id = + it->second.is_stylus ? kStylusNotificationId : address; message_center::MessageCenter::Get()->RemoveNotification( - kStylusNotificationId, false /* by_user */); - return; - } - - // If last_used_profile_ is NULL then no notification has been posted yet. - if (notification_profile_) { - g_browser_process->notification_ui_manager()->CancelById( - address, NotificationUIManager::GetProfileID(notification_profile_)); + notification_id, false /* by_user */); } }
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer.h b/chrome/browser/chromeos/power/peripheral_battery_observer.h index c3d43bc..07b5558 100644 --- a/chrome/browser/chromeos/power/peripheral_battery_observer.h +++ b/chrome/browser/chromeos/power/peripheral_battery_observer.h
@@ -15,8 +15,6 @@ #include "chromeos/dbus/power_manager_client.h" #include "device/bluetooth/bluetooth_adapter.h" -class Profile; - namespace chromeos { class BluetoothDevice; @@ -24,7 +22,8 @@ // This observer listens for peripheral device battery status and shows // notifications for low battery conditions. -// TODO(sammiequon): Investigate whether we can move this class to //ash. +// TODO(sammiequon): Investigate whether we can move this class to +// //ash/system/power. class PeripheralBatteryObserver : public PowerManagerClient::Observer, public device::BluetoothAdapter::Observer { public: @@ -36,12 +35,12 @@ void set_testing_clock(base::TickClock* clock) { testing_clock_ = clock; } - // PowerManagerClient::Observer implementation. + // PowerManagerClient::Observer: void PeripheralBatteryStatusReceived(const std::string& path, const std::string& name, int level) override; - // device::BluetoothAdapter::Observer implementation. + // device::BluetoothAdapter::Observer: void DeviceChanged(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) override; void DeviceRemoved(device::BluetoothAdapter* adapter, @@ -59,6 +58,7 @@ // Battery level within range [0, 100], and -1 for unknown level. int level = -1; base::TimeTicks last_notification_timestamp; + bool is_stylus = false; }; void InitializeOnBluetoothReady( @@ -83,9 +83,6 @@ // Used only for helping test. Not owned and can be NULL. base::TickClock* testing_clock_; - // Record the profile used when adding message center notifications. - Profile* notification_profile_; - std::unique_ptr<base::WeakPtrFactory<PeripheralBatteryObserver>> weakptr_factory_;
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer_browsertest.cc b/chrome/browser/chromeos/power/peripheral_battery_observer_browsertest.cc deleted file mode 100644 index 992e0fa..0000000 --- a/chrome/browser/chromeos/power/peripheral_battery_observer_browsertest.cc +++ /dev/null
@@ -1,220 +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 "chrome/browser/chromeos/power/peripheral_battery_observer.h" - -#include "base/command_line.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/test/simple_test_tick_clock.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/notifications/notification_ui_manager.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "content/public/test/test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/devices/touchscreen_device.h" -#include "ui/events/test/device_data_manager_test_api.h" -#include "ui/message_center/message_center.h" -#include "ui/message_center/notification.h" - -using ::testing::_; -using ::testing::InSequence; -using ::testing::Return; -using ::testing::SaveArg; - -namespace { - -const char kTestBatteryPath[] = "/sys/class/power_supply/hid-AA:BB:CC-battery"; -const char kTestBatteryAddress[] = "cc:bb:aa"; -const char kTestDeviceName[] = "test device"; - -} // namespace - -namespace chromeos { - -class PeripheralBatteryObserverTest : public InProcessBrowserTest { - public: - PeripheralBatteryObserverTest() {} - ~PeripheralBatteryObserverTest() override {} - - void SetUp() override { - InProcessBrowserTest::SetUp(); - chromeos::DBusThreadManager::Initialize(); - } - - void SetUpOnMainThread() override { - observer_.reset(new PeripheralBatteryObserver()); - } - - void TearDownOnMainThread() override { observer_.reset(); } - - protected: - std::unique_ptr<PeripheralBatteryObserver> observer_; - - private: - DISALLOW_COPY_AND_ASSIGN(PeripheralBatteryObserverTest); -}; - -IN_PROC_BROWSER_TEST_F(PeripheralBatteryObserverTest, Basic) { - base::SimpleTestTickClock clock; - observer_->set_testing_clock(&clock); - - NotificationUIManager* notification_manager = - g_browser_process->notification_ui_manager(); - - // Level 50 at time 100, no low-battery notification. - clock.Advance(base::TimeDelta::FromSeconds(100)); - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, 50); - EXPECT_EQ(observer_->batteries_.count(kTestBatteryAddress), 1u); - - const PeripheralBatteryObserver::BatteryInfo& info = - observer_->batteries_[kTestBatteryAddress]; - - EXPECT_EQ(info.name, kTestDeviceName); - EXPECT_EQ(info.level, 50); - EXPECT_EQ(info.last_notification_timestamp, base::TimeTicks()); - EXPECT_FALSE(notification_manager->FindById( - kTestBatteryAddress, - NotificationUIManager::GetProfileID( - ProfileManager::GetPrimaryUserProfile())) != NULL); - - // Level 5 at time 110, low-battery notification. - clock.Advance(base::TimeDelta::FromSeconds(10)); - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, 5); - EXPECT_EQ(info.level, 5); - EXPECT_EQ(info.last_notification_timestamp, clock.NowTicks()); - EXPECT_TRUE(notification_manager->FindById( - kTestBatteryAddress, - NotificationUIManager::GetProfileID( - ProfileManager::GetPrimaryUserProfile())) != NULL); - - // Verify that the low-battery notification for stylus does not show up. - EXPECT_TRUE(message_center::MessageCenter::Get()->FindVisibleNotificationById( - PeripheralBatteryObserver::kStylusNotificationId) == nullptr); - - // Level -1 at time 115, cancel previous notification - clock.Advance(base::TimeDelta::FromSeconds(5)); - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, -1); - EXPECT_EQ(info.level, 5); - EXPECT_EQ(info.last_notification_timestamp, - clock.NowTicks() - base::TimeDelta::FromSeconds(5)); - EXPECT_FALSE(notification_manager->FindById( - kTestBatteryAddress, - NotificationUIManager::GetProfileID( - ProfileManager::GetPrimaryUserProfile())) != NULL); - - // Level 50 at time 120, no low-battery notification. - clock.Advance(base::TimeDelta::FromSeconds(5)); - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, 50); - EXPECT_EQ(info.level, 50); - EXPECT_EQ(info.last_notification_timestamp, - clock.NowTicks() - base::TimeDelta::FromSeconds(10)); - EXPECT_FALSE(notification_manager->FindById( - kTestBatteryAddress, - NotificationUIManager::GetProfileID( - ProfileManager::GetPrimaryUserProfile())) != NULL); - - // Level 5 at time 130, no low-battery notification (throttling). - clock.Advance(base::TimeDelta::FromSeconds(10)); - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, 5); - EXPECT_EQ(info.level, 5); - EXPECT_EQ(info.last_notification_timestamp, - clock.NowTicks() - base::TimeDelta::FromSeconds(20)); - EXPECT_FALSE(notification_manager->FindById( - kTestBatteryAddress, - NotificationUIManager::GetProfileID( - ProfileManager::GetPrimaryUserProfile())) != NULL); -} - -IN_PROC_BROWSER_TEST_F(PeripheralBatteryObserverTest, InvalidBatteryInfo) { - observer_->PeripheralBatteryStatusReceived("invalid-path", kTestDeviceName, - 10); - EXPECT_TRUE(observer_->batteries_.empty()); - - observer_->PeripheralBatteryStatusReceived( - "/sys/class/power_supply/hid-battery", kTestDeviceName, 10); - EXPECT_TRUE(observer_->batteries_.empty()); - - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, -2); - EXPECT_TRUE(observer_->batteries_.empty()); - - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, 101); - EXPECT_TRUE(observer_->batteries_.empty()); - - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, -1); - EXPECT_TRUE(observer_->batteries_.empty()); -} - -IN_PROC_BROWSER_TEST_F(PeripheralBatteryObserverTest, DeviceRemove) { - NotificationUIManager* notification_manager = - g_browser_process->notification_ui_manager(); - - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, - kTestDeviceName, 5); - EXPECT_EQ(observer_->batteries_.count(kTestBatteryAddress), 1u); - EXPECT_TRUE(notification_manager->FindById( - kTestBatteryAddress, - NotificationUIManager::GetProfileID( - ProfileManager::GetPrimaryUserProfile())) != NULL); - - observer_->RemoveBattery(kTestBatteryAddress); - EXPECT_FALSE(notification_manager->FindById( - kTestBatteryAddress, - NotificationUIManager::GetProfileID( - ProfileManager::GetPrimaryUserProfile())) != NULL); -} - -IN_PROC_BROWSER_TEST_F(PeripheralBatteryObserverTest, StylusNotification) { - const std::string kTestStylusName = "test_stylus"; - - // Add an external stylus to our test device manager. - ui::TouchscreenDevice stylus(0 /* id */, ui::INPUT_DEVICE_EXTERNAL, - kTestStylusName, gfx::Size(), - 1 /* touch_points */); - stylus.sys_path = base::FilePath(kTestBatteryPath); - stylus.is_stylus = true; - - ui::test::DeviceDataManagerTestAPI test_api; - test_api.SetTouchscreenDevices({stylus}); - - message_center::MessageCenter* message_center = - message_center::MessageCenter::Get(); - - // Verify that when the battery level is 50, no stylus low battery - // notification is shown. - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, - 50); - EXPECT_TRUE(message_center->FindVisibleNotificationById( - PeripheralBatteryObserver::kStylusNotificationId) == nullptr); - - // Verify that when the battery level is 5, a stylus low battery notification - // is shown. Also check that a non stylus device low battery notification will - // not show up. - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, - 5); - EXPECT_TRUE(message_center->FindVisibleNotificationById( - PeripheralBatteryObserver::kStylusNotificationId) != nullptr); - EXPECT_TRUE(message_center->FindVisibleNotificationById( - kTestBatteryAddress) == nullptr); - - // Verify that when the battery level is -1, the previous stylus low battery - // notification is cancelled. - observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, - -1); - EXPECT_TRUE(message_center->FindVisibleNotificationById( - PeripheralBatteryObserver::kStylusNotificationId) == nullptr); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer_unittest.cc b/chrome/browser/chromeos/power/peripheral_battery_observer_unittest.cc new file mode 100644 index 0000000..83e79463 --- /dev/null +++ b/chrome/browser/chromeos/power/peripheral_battery_observer_unittest.cc
@@ -0,0 +1,193 @@ +// 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 "chrome/browser/chromeos/power/peripheral_battery_observer.h" + +#include "ash/test/ash_test_base.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/test/simple_test_tick_clock.h" +#include "ui/events/devices/touchscreen_device.h" +#include "ui/events/test/device_data_manager_test_api.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/notification.h" + +namespace { + +const char kTestBatteryPath[] = "/sys/class/power_supply/hid-AA:BB:CC-battery"; +const char kTestBatteryAddress[] = "cc:bb:aa"; +const char kTestDeviceName[] = "test device"; + +} // namespace + +namespace chromeos { + +class PeripheralBatteryObserverTest : public ash::AshTestBase { + public: + PeripheralBatteryObserverTest() {} + ~PeripheralBatteryObserverTest() override {} + + void SetUp() override { + ash::AshTestBase::SetUp(); + observer_ = base::MakeUnique<PeripheralBatteryObserver>(); + } + + void TearDown() override { + observer_.reset(); + ash::AshTestBase::TearDown(); + } + + protected: + std::unique_ptr<PeripheralBatteryObserver> observer_; + + private: + DISALLOW_COPY_AND_ASSIGN(PeripheralBatteryObserverTest); +}; + +TEST_F(PeripheralBatteryObserverTest, Basic) { + base::SimpleTestTickClock clock; + observer_->set_testing_clock(&clock); + + message_center::MessageCenter* message_center = + message_center::MessageCenter::Get(); + + // Level 50 at time 100, no low-battery notification. + clock.Advance(base::TimeDelta::FromSeconds(100)); + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + 50); + EXPECT_EQ(1u, observer_->batteries_.count(kTestBatteryAddress)); + + const PeripheralBatteryObserver::BatteryInfo& info = + observer_->batteries_[kTestBatteryAddress]; + + EXPECT_EQ(kTestDeviceName, info.name); + EXPECT_EQ(50, info.level); + EXPECT_EQ(base::TimeTicks(), info.last_notification_timestamp); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) == nullptr); + + // Level 5 at time 110, low-battery notification. + clock.Advance(base::TimeDelta::FromSeconds(10)); + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + 5); + EXPECT_EQ(5, info.level); + EXPECT_EQ(clock.NowTicks(), info.last_notification_timestamp); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) != nullptr); + + // Verify that the low-battery notification for stylus does not show up. + EXPECT_FALSE(message_center->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) != + nullptr); + + // Level -1 at time 115, cancel previous notification + clock.Advance(base::TimeDelta::FromSeconds(5)); + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + -1); + EXPECT_EQ(5, info.level); + EXPECT_EQ(clock.NowTicks() - base::TimeDelta::FromSeconds(5), + info.last_notification_timestamp); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) == nullptr); + + // Level 50 at time 120, no low-battery notification. + clock.Advance(base::TimeDelta::FromSeconds(5)); + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + 50); + EXPECT_EQ(50, info.level); + EXPECT_EQ(clock.NowTicks() - base::TimeDelta::FromSeconds(10), + info.last_notification_timestamp); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) == nullptr); + + // Level 5 at time 130, no low-battery notification (throttling). + clock.Advance(base::TimeDelta::FromSeconds(10)); + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + 5); + EXPECT_EQ(5, info.level); + EXPECT_EQ(clock.NowTicks() - base::TimeDelta::FromSeconds(20), + info.last_notification_timestamp); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) == nullptr); +} + +TEST_F(PeripheralBatteryObserverTest, InvalidBatteryInfo) { + observer_->PeripheralBatteryStatusReceived("invalid-path", kTestDeviceName, + 10); + EXPECT_TRUE(observer_->batteries_.empty()); + + observer_->PeripheralBatteryStatusReceived( + "/sys/class/power_supply/hid-battery", kTestDeviceName, 10); + EXPECT_TRUE(observer_->batteries_.empty()); + + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + -2); + EXPECT_TRUE(observer_->batteries_.empty()); + + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + 101); + EXPECT_TRUE(observer_->batteries_.empty()); + + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + -1); + EXPECT_TRUE(observer_->batteries_.empty()); +} + +TEST_F(PeripheralBatteryObserverTest, DeviceRemove) { + message_center::MessageCenter* message_center = + message_center::MessageCenter::Get(); + + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestDeviceName, + 5); + EXPECT_EQ(1u, observer_->batteries_.count(kTestBatteryAddress)); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) != nullptr); + + observer_->RemoveBattery(kTestBatteryAddress); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) == nullptr); +} + +TEST_F(PeripheralBatteryObserverTest, StylusNotification) { + const std::string kTestStylusName = "test_stylus"; + + // Add an external stylus to our test device manager. + ui::TouchscreenDevice stylus(0 /* id */, ui::INPUT_DEVICE_EXTERNAL, + kTestStylusName, gfx::Size(), + 1 /* touch_points */); + stylus.sys_path = base::FilePath(kTestBatteryPath); + stylus.is_stylus = true; + + ui::test::DeviceDataManagerTestAPI test_api; + test_api.SetTouchscreenDevices({stylus}); + + message_center::MessageCenter* message_center = + message_center::MessageCenter::Get(); + + // Verify that when the battery level is 50, no stylus low battery + // notification is shown. + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, + 50); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) == nullptr); + + // Verify that when the battery level is 5, a stylus low battery notification + // is shown. Also check that a non stylus device low battery notification will + // not show up. + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, + 5); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) != nullptr); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + kTestBatteryAddress) == nullptr); + + // Verify that when the battery level is -1, the previous stylus low battery + // notification is cancelled. + observer_->PeripheralBatteryStatusReceived(kTestBatteryPath, kTestStylusName, + -1); + EXPECT_TRUE(message_center->FindVisibleNotificationById( + PeripheralBatteryObserver::kStylusNotificationId) == nullptr); +} + +} // namespace chromeos
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index a90431d..5789cf8 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc
@@ -41,6 +41,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/resource_dispatcher_host.h" +#include "extensions/browser/extension_file_task_runner.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" @@ -132,9 +133,9 @@ off_store_install_allow_reason_(OffStoreInstallDisallowed), did_handle_successfully_(true), error_on_unsupported_requirements_(false), + installer_task_runner_(GetExtensionFileTaskRunner()), update_from_settings_page_(false), install_flags_(kInstallFlagNone) { - installer_task_runner_ = service_weak->GetFileTaskRunner(); if (!approval) return;
diff --git a/chrome/browser/extensions/extension_assets_manager_chromeos.cc b/chrome/browser/extensions/extension_assets_manager_chromeos.cc index ee709fd..916d3514 100644 --- a/chrome/browser/extensions/extension_assets_manager_chromeos.cc +++ b/chrome/browser/extensions/extension_assets_manager_chromeos.cc
@@ -20,7 +20,6 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" #include "chromeos/chromeos_switches.h" #include "components/prefs/pref_registry_simple.h" @@ -28,8 +27,8 @@ #include "components/prefs/scoped_user_pref_update.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_thread.h" +#include "extensions/browser/extension_file_task_runner.h" #include "extensions/browser/extension_prefs.h" -#include "extensions/browser/extension_system.h" #include "extensions/common/extension.h" #include "extensions/common/extension_urls.h" #include "extensions/common/file_util.h" @@ -247,15 +246,6 @@ } // static -base::SequencedTaskRunner* ExtensionAssetsManagerChromeOS::GetFileTaskRunner( - Profile* profile) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - ExtensionService* extension_service = - ExtensionSystem::Get(profile)->extension_service(); - return extension_service->GetFileTaskRunner(); -} - -// static bool ExtensionAssetsManagerChromeOS::CanShareAssets( const Extension* extension, const base::FilePath& unpacked_extension_root) { @@ -298,13 +288,10 @@ !user_manager->IsLoggedInAsUserWithGaiaAccount()) { // Don't cache anything in shared location for ephemeral user or special // user types. - ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( + GetExtensionFileTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension, - id, - version, - unpacked_extension_root, - local_install_dir, + base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension, id, + version, unpacked_extension_root, local_install_dir, callback)); return; } @@ -335,9 +322,8 @@ users->AppendString(user_id); // unpacked_extension_root will be deleted by CrxInstaller. - ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( - FROM_HERE, - base::Bind(callback, base::FilePath(shared_path))); + GetExtensionFileTaskRunner()->PostTask( + FROM_HERE, base::Bind(callback, base::FilePath(shared_path))); } else { // Desired version is not found in shared location. ExtensionAssetsManagerHelper* helper = @@ -345,12 +331,10 @@ if (helper->RecordSharedInstall(id, version, unpacked_extension_root, local_install_dir, profile, callback)) { // There is no install in progress for given <id, version> so run install. - ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( + GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::Bind(&ExtensionAssetsManagerChromeOS::InstallSharedExtension, - id, - version, - unpacked_extension_root)); + id, version, unpacked_extension_root)); } } } @@ -386,14 +370,11 @@ for (size_t i = 0; i < pending_installs.size(); i++) { ExtensionAssetsManagerHelper::PendingInstallInfo& info = pending_installs[i]; - ExtensionAssetsManagerChromeOS::GetFileTaskRunner(info.profile)->PostTask( + GetExtensionFileTaskRunner()->PostTask( FROM_HERE, - base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension, - id, - version, - info.unpacked_extension_root, - info.local_install_dir, - info.callback)); + base::Bind(&ExtensionAssetsManagerChromeOS::InstallLocalExtension, id, + version, info.unpacked_extension_root, + info.local_install_dir, info.callback)); } return; } @@ -417,9 +398,8 @@ pending_installs[i]; users->AppendString(info.profile->GetProfileUserName()); - ExtensionAssetsManagerChromeOS::GetFileTaskRunner(info.profile)->PostTask( - FROM_HERE, - base::Bind(info.callback, shared_version_dir)); + GetExtensionFileTaskRunner()->PostTask( + FROM_HERE, base::Bind(info.callback, shared_version_dir)); } version_info->Set(kSharedExtensionUsers, std::move(users)); extension_info_weak->SetWithoutPathExpansion(version, @@ -479,7 +459,7 @@ NOTREACHED(); continue; } - ExtensionAssetsManagerChromeOS::GetFileTaskRunner(profile)->PostTask( + GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::Bind(&ExtensionAssetsManagerChromeOS::DeleteSharedVersion, base::FilePath(shared_path)));
diff --git a/chrome/browser/extensions/extension_assets_manager_chromeos.h b/chrome/browser/extensions/extension_assets_manager_chromeos.h index 29212d3..1ef3090 100644 --- a/chrome/browser/extensions/extension_assets_manager_chromeos.h +++ b/chrome/browser/extensions/extension_assets_manager_chromeos.h
@@ -18,7 +18,6 @@ namespace base { class DictionaryValue; -class SequencedTaskRunner; } namespace extensions { @@ -73,10 +72,6 @@ ExtensionAssetsManagerChromeOS(); ~ExtensionAssetsManagerChromeOS() override; - // Should be called on UI thread to get associated file task runner for - // the profile. - static base::SequencedTaskRunner* GetFileTaskRunner(Profile* profile); - // Return |true| if |extension| can be installed in a shared place for all // users on the device. static bool CanShareAssets(const Extension* extension,
diff --git a/chrome/browser/extensions/extension_garbage_collector.cc b/chrome/browser/extensions/extension_garbage_collector.cc index 0ccf5b8..5b74ac1 100644 --- a/chrome/browser/extensions/extension_garbage_collector.cc +++ b/chrome/browser/extensions/extension_garbage_collector.cc
@@ -28,6 +28,7 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" +#include "extensions/browser/extension_file_task_runner.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" @@ -201,7 +202,7 @@ ExtensionService* service = ExtensionSystem::Get(context_)->extension_service(); - if (!service->GetFileTaskRunner()->PostTask( + if (!GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&GarbageCollectExtensionsOnFileThread, service->install_directory(), extension_paths))) {
diff --git a/chrome/browser/extensions/extension_garbage_collector_chromeos.cc b/chrome/browser/extensions/extension_garbage_collector_chromeos.cc index a2f7e65..99ba05e9 100644 --- a/chrome/browser/extensions/extension_garbage_collector_chromeos.cc +++ b/chrome/browser/extensions/extension_garbage_collector_chromeos.cc
@@ -7,9 +7,8 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/extension_assets_manager_chromeos.h" #include "chrome/browser/extensions/extension_garbage_collector_chromeos.h" -#include "chrome/browser/extensions/extension_service.h" #include "components/user_manager/user_manager.h" -#include "extensions/browser/extension_system.h" +#include "extensions/browser/extension_file_task_runner.h" namespace extensions { @@ -77,9 +76,7 @@ void ExtensionGarbageCollectorChromeOS::GarbageCollectSharedExtensions() { std::multimap<std::string, base::FilePath> paths; if (ExtensionAssetsManagerChromeOS::CleanUpSharedExtensions(&paths)) { - ExtensionService* service = - ExtensionSystem::Get(context_)->extension_service(); - if (!service->GetFileTaskRunner()->PostTask( + if (!GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::Bind(&GarbageCollectExtensionsOnFileThread, ExtensionAssetsManagerChromeOS::GetSharedInstallDir(),
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 95ca0f3..f46cbae 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -563,7 +563,7 @@ // Delete extension_path since we're not creating a CrxInstaller // that would do it for us. if (file_ownership_passed && - !GetFileTaskRunner()->PostTask( + !extensions::GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&extensions::file_util::DeleteFile, file.path, false))) NOTREACHED(); @@ -821,7 +821,7 @@ // Tell the backend to start deleting installed extensions on the file thread. if (!Manifest::IsUnpackedLocation(extension->location())) { - if (!GetFileTaskRunner()->PostTask( + if (!extensions::GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&ExtensionService::UninstallExtensionOnFileThread, extension->id(), profile_, install_directory_, @@ -1772,7 +1772,7 @@ // Delete the extension directory since we're not going to // load it. - if (!GetFileTaskRunner()->PostTask( + if (!extensions::GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&extensions::file_util::DeleteFile, extension->path(), true))) { NOTREACHED(); @@ -2508,12 +2508,6 @@ } } -base::SequencedTaskRunner* ExtensionService::GetFileTaskRunner() { - // TODO(devlin): Update callers to use GetExtensionFileTaskRunner() - // directly. - return extensions::GetExtensionFileTaskRunner().get(); -} - // Used only by test code. void ExtensionService::UnloadAllExtensionsInternal() { profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions();
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index 9c9e05b..f30a75ac 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h
@@ -46,7 +46,6 @@ namespace base { class CommandLine; -class SequencedTaskRunner; } namespace content { @@ -364,9 +363,6 @@ extensions::InstallGate* install_delayer); void UnregisterInstallGate(extensions::InstallGate* install_delayer); - // Returns task runner for crx installation file I/O operations. - base::SequencedTaskRunner* GetFileTaskRunner(); - ////////////////////////////////////////////////////////////////////////////// // Simple Accessors
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc index a94de9c..b8b6fd4 100644 --- a/chrome/browser/extensions/process_manager_browsertest.cc +++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/browser_action_test_util.h" @@ -24,6 +25,7 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/app_modal/javascript_dialog_manager.h" #include "components/guest_view/browser/test_guest_view_manager.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/navigation_entry.h" @@ -1266,4 +1268,40 @@ } } +// Tests that we correctly account for vanilla web URLs that may be in the +// same SiteInstance as a hosted app, and display alerts correctly. +// https://crbug.com/746517. +IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, HostedAppAlerts) { + ASSERT_TRUE(embedded_test_server()->Start()); + scoped_refptr<const Extension> extension = + LoadExtension(test_data_dir_.AppendASCII("hosted_app")); + ASSERT_TRUE(extension); + + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL hosted_app_url("http://localhost/extensions/hosted_app/main.html"); + NavigateToURL(hosted_app_url); + EXPECT_EQ(hosted_app_url, tab->GetLastCommittedURL()); + ProcessManager* pm = ProcessManager::Get(profile()); + EXPECT_EQ(extension, pm->GetExtensionForWebContents(tab)); + app_modal::JavaScriptDialogManager* js_dialog_manager = + app_modal::JavaScriptDialogManager::GetInstance(); + base::string16 hosted_app_title = base::ASCIIToUTF16("hosted_app"); + EXPECT_EQ(hosted_app_title, js_dialog_manager->GetTitle( + tab, tab->GetLastCommittedURL().GetOrigin())); + + GURL web_url = embedded_test_server()->GetURL("/title1.html"); + ASSERT_TRUE(content::ExecuteScript( + tab, base::StringPrintf("window.open('%s');", web_url.spec().c_str()))); + content::WebContents* new_tab = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_NE(new_tab, tab); + EXPECT_TRUE(content::WaitForLoadStop(new_tab)); + EXPECT_EQ(web_url, new_tab->GetLastCommittedURL()); + EXPECT_EQ(nullptr, pm->GetExtensionForWebContents(new_tab)); + EXPECT_NE(hosted_app_title, + js_dialog_manager->GetTitle( + new_tab, new_tab->GetLastCommittedURL().GetOrigin())); +} + } // namespace extensions
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 8a91c48..893a7e07 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -363,12 +363,6 @@ const char kEnableMaterialDesignFeedbackDescription[] = "If enabled, reporting an issue will load the Material Design feedback UI."; -const char kEnableMaterialDesignPolicyPageName[] = - "Enable Material Design policy page"; -const char kEnableMaterialDesignPolicyPageDescription[] = - "If enabled, the chrome://md-policy URL loads the Material Design policy " - "page."; - const char kEnableMidiManagerDynamicInstantiationName[] = "MIDIManager dynamic instantiation for Web MIDI."; const char kEnableMidiManagerDynamicInstantiationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index d5487e7..fa6363e 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -242,9 +242,6 @@ extern const char kEnableMaterialDesignFeedbackName[]; extern const char kEnableMaterialDesignFeedbackDescription[]; -extern const char kEnableMaterialDesignPolicyPageName[]; -extern const char kEnableMaterialDesignPolicyPageDescription[]; - extern const char kEnableMidiManagerDynamicInstantiationName[]; extern const char kEnableMidiManagerDynamicInstantiationDescription[];
diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.cc b/chrome/browser/offline_pages/android/offline_page_bridge.cc index 2047073..f5f35b1c 100644 --- a/chrome/browser/offline_pages/android/offline_page_bridge.cc +++ b/chrome/browser/offline_pages/android/offline_page_bridge.cc
@@ -30,6 +30,7 @@ #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_model.h" +#include "components/offline_pages/core/offline_page_types.h" #include "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_delegate.h" #include "components/offline_pages/core/request_header/offline_page_header.h" #include "content/public/browser/browser_context.h" @@ -470,10 +471,8 @@ j_callback_ref.Reset(env, j_callback_obj); OfflinePageUtils::SelectPageForURL( - browser_context_, - GURL(ConvertJavaStringToUTF8(env, j_online_url)), - OfflinePageModel::URLSearchMode::SEARCH_BY_ALL_URLS, - tab_id, + browser_context_, GURL(ConvertJavaStringToUTF8(env, j_online_url)), + URLSearchMode::SEARCH_BY_ALL_URLS, tab_id, base::Bind(&SingleOfflinePageItemCallback, j_callback_ref)); }
diff --git a/chrome/browser/offline_pages/offline_page_request_job.cc b/chrome/browser/offline_pages/offline_page_request_job.cc index 229f559..0945ce5 100644 --- a/chrome/browser/offline_pages/offline_page_request_job.cc +++ b/chrome/browser/offline_pages/offline_page_request_job.cc
@@ -416,16 +416,10 @@ } OfflinePageUtils::SelectPageForURL( - web_contents->GetBrowserContext(), - url, - OfflinePageModel::URLSearchMode::SEARCH_BY_ALL_URLS, + web_contents->GetBrowserContext(), url, URLSearchMode::SEARCH_BY_ALL_URLS, tab_id, - base::Bind(&SucceededToFindOfflinePage, - url, - offline_header, - network_state, - job, - web_contents_getter)); + base::Bind(&SucceededToFindOfflinePage, url, offline_header, + network_state, job, web_contents_getter)); } void FindPageWithOfflineIDDone(
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.cc b/chrome/browser/offline_pages/offline_page_tab_helper.cc index 06420a5e..cbd137e 100644 --- a/chrome/browser/offline_pages/offline_page_tab_helper.cc +++ b/chrome/browser/offline_pages/offline_page_tab_helper.cc
@@ -167,10 +167,8 @@ } OfflinePageUtils::SelectPageForURL( - web_contents()->GetBrowserContext(), - navigated_url, - OfflinePageModel::URLSearchMode::SEARCH_BY_ALL_URLS, - tab_id, + web_contents()->GetBrowserContext(), navigated_url, + URLSearchMode::SEARCH_BY_ALL_URLS, tab_id, base::Bind(&OfflinePageTabHelper::SelectPageForURLDone, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/offline_pages/offline_page_utils.cc b/chrome/browser/offline_pages/offline_page_utils.cc index c86158d..f017a45e 100644 --- a/chrome/browser/offline_pages/offline_page_utils.cc +++ b/chrome/browser/offline_pages/offline_page_utils.cc
@@ -147,7 +147,7 @@ void OfflinePageUtils::SelectPageForURL( content::BrowserContext* browser_context, const GURL& url, - OfflinePageModel::URLSearchMode url_search_mode, + URLSearchMode url_search_mode, int tab_id, const base::Callback<void(const OfflinePageItem*)>& callback) { OfflinePageModel* offline_page_model = @@ -275,7 +275,7 @@ }; offline_page_model->GetPagesByURL( - url, OfflinePageModel::URLSearchMode::SEARCH_BY_ALL_URLS, + url, URLSearchMode::SEARCH_BY_ALL_URLS, base::Bind(continuation, browser_context, url, callback)); }
diff --git a/chrome/browser/offline_pages/offline_page_utils.h b/chrome/browser/offline_pages/offline_page_utils.h index 1d6dc7a..1c1ac36 100644 --- a/chrome/browser/offline_pages/offline_page_utils.h +++ b/chrome/browser/offline_pages/offline_page_utils.h
@@ -62,7 +62,7 @@ static void SelectPageForURL( content::BrowserContext* browser_context, const GURL& url, - OfflinePageModel::URLSearchMode url_search_mode, + URLSearchMode url_search_mode, int tab_id, const base::Callback<void(const OfflinePageItem*)>& callback);
diff --git a/chrome/browser/profiling_host/BUILD.gn b/chrome/browser/profiling_host/BUILD.gn index 8d5fa33b..e3bcbd7e 100644 --- a/chrome/browser/profiling_host/BUILD.gn +++ b/chrome/browser/profiling_host/BUILD.gn
@@ -7,6 +7,8 @@ if (enable_oop_heap_profiling) { static_library("profiling_host") { sources = [ + "chrome_browser_main_extra_parts_profiling.cc", + "chrome_browser_main_extra_parts_profiling.h", "profiling_process_host.cc", "profiling_process_host.h", ]
diff --git a/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc new file mode 100644 index 0000000..0fa2fd4 --- /dev/null +++ b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc
@@ -0,0 +1,21 @@ +// Copyright 2017 The Chromium Authors. 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/profiling_host/chrome_browser_main_extra_parts_profiling.h" + +#include "base/command_line.h" +#include "chrome/browser/profiling_host/profiling_process_host.h" +#include "chrome/common/chrome_switches.h" + +ChromeBrowserMainExtraPartsProfiling::ChromeBrowserMainExtraPartsProfiling() = + default; +ChromeBrowserMainExtraPartsProfiling::~ChromeBrowserMainExtraPartsProfiling() = + default; + +void ChromeBrowserMainExtraPartsProfiling::ServiceManagerConnectionStarted( + content::ServiceManagerConnection* connection) { + const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess(); + if (cmdline.HasSwitch(switches::kMemlog)) + profiling::ProfilingProcessHost::EnsureStarted(connection); +}
diff --git a/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.h b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.h new file mode 100644 index 0000000..e3776d5a --- /dev/null +++ b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.h
@@ -0,0 +1,26 @@ +// Copyright 2017 The Chromium Authors. 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_PROFILING_HOST_CHROME_BROWSER_MAIN_EXTRA_PARTS_PROFILING_H_ +#define CHROME_BROWSER_PROFILING_HOST_CHROME_BROWSER_MAIN_EXTRA_PARTS_PROFILING_H_ + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "chrome/browser/chrome_browser_main_extra_parts.h" + +class ChromeBrowserMainExtraPartsProfiling + : public ChromeBrowserMainExtraParts { + public: + ChromeBrowserMainExtraPartsProfiling(); + ~ChromeBrowserMainExtraPartsProfiling() override; + + private: + // ChromeBrowserMainExtraParts overrides. + void ServiceManagerConnectionStarted( + content::ServiceManagerConnection* connection) override; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsProfiling); +}; + +#endif // CHROME_BROWSER_PROFILING_HOST_CHROME_BROWSER_MAIN_EXTRA_PARTS_PROFILING_H_
diff --git a/chrome/browser/profiling_host/profiling_process_host.cc b/chrome/browser/profiling_host/profiling_process_host.cc index df6875a..4b267eb 100644 --- a/chrome/browser/profiling_host/profiling_process_host.cc +++ b/chrome/browser/profiling_host/profiling_process_host.cc
@@ -5,90 +5,142 @@ #include "chrome/browser/profiling_host/profiling_process_host.h" #include "base/command_line.h" +#include "base/path_service.h" #include "base/strings/string_number_conversions.h" +#include "base/task_scheduler/post_task.h" #include "build/build_config.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/profiling/constants.mojom.h" -#include "chrome/common/profiling/memlog.mojom.h" -#include "chrome/common/profiling/memlog_sender.h" #include "chrome/common/profiling/profiling_constants.h" +#include "content/public/browser/browser_child_process_host.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/common/bind_interface_helpers.h" +#include "content/public/common/child_process_host.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_manager_connection.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/public/cpp/system/platform_handle.h" -#include "services/service_manager/public/cpp/connector.h" namespace profiling { -namespace { - -ProfilingProcessHost* pph_singleton = nullptr; - -void BindToBrowserConnector(service_manager::mojom::ConnectorRequest request) { - if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&BindToBrowserConnector, std::move(request))); - return; - } - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindConnectorRequest(std::move(request)); -} - -} // namespace - ProfilingProcessHost::ProfilingProcessHost() { - pph_singleton = this; - LaunchAsService(); + Add(this); + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, + content::NotificationService::AllBrowserContextsAndSources()); } ProfilingProcessHost::~ProfilingProcessHost() { - pph_singleton = nullptr; + Remove(this); } -// static -ProfilingProcessHost* ProfilingProcessHost::EnsureStarted() { - static ProfilingProcessHost host; - return &host; +void ProfilingProcessHost::BrowserChildProcessLaunchedAndConnected( + const content::ChildProcessData& data) { + if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) { + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO) + ->PostTask( + FROM_HERE, + base::BindOnce( + &ProfilingProcessHost::BrowserChildProcessLaunchedAndConnected, + base::Unretained(this), data)); + return; + } + content::BrowserChildProcessHost* host = + content::BrowserChildProcessHost::FromID(data.id); + if (!host) + return; + + // Tell the child process to start profiling. + profiling::mojom::MemlogClientPtr memlog_client; + profiling::mojom::MemlogClientRequest request = + mojo::MakeRequest(&memlog_client); + BindInterface(host->GetHost(), std::move(request)); + base::ProcessId pid = base::GetProcId(data.handle); + StartProfilingForClient(std::move(memlog_client), pid); } -// static -ProfilingProcessHost* ProfilingProcessHost::Get() { - return pph_singleton; -} +void ProfilingProcessHost::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + if (type != content::NOTIFICATION_RENDERER_PROCESS_CREATED) + return; -// static -void ProfilingProcessHost::AddSwitchesToChildCmdLine( - base::CommandLine* child_cmd_line) { - // TODO(ajwong): Figure out how to trace the zygote process. - if (child_cmd_line->GetSwitchValueASCII(switches::kProcessType) == - switches::kZygoteProcess) { + if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) { + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO) + ->PostTask(FROM_HERE, base::BindOnce(&ProfilingProcessHost::Observe, + base::Unretained(this), type, + source, details)); return; } - // TODO(ajwong): Change this to just reuse the --memlog flag. There is no - // need for a separate pipe flag. - // - // Zero is browser which is specified in LaunchAsService. - static int sender_id = 1; - child_cmd_line->AppendSwitchASCII(switches::kMemlogPipe, - base::IntToString(sender_id++)); + // Tell the child process to start profiling. + content::RenderProcessHost* host = + content::Source<content::RenderProcessHost>(source).ptr(); + profiling::mojom::MemlogClientPtr memlog_client; + profiling::mojom::MemlogClientRequest request = + mojo::MakeRequest(&memlog_client); + content::BindInterface(host, std::move(request)); + base::ProcessId pid = base::GetProcId(host->GetHandle()); + + StartProfilingForClient(std::move(memlog_client), pid); +} + +void ProfilingProcessHost::StartProfilingForClient( + profiling::mojom::MemlogClientPtr memlog_client, + base::ProcessId pid) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + + mojo::edk::PlatformChannelPair data_channel; + + memlog_->AddSender( + pid, + mojo::WrapPlatformFile(data_channel.PassServerHandle().release().handle)); + memlog_client->StartProfiling( + mojo::WrapPlatformFile(data_channel.PassClientHandle().release().handle)); +} + +// static +ProfilingProcessHost* ProfilingProcessHost::EnsureStarted( + content::ServiceManagerConnection* connection) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + ProfilingProcessHost* host = GetInstance(); + host->MakeConnector(connection); + host->LaunchAsService(); + return host; +} + +// static +ProfilingProcessHost* ProfilingProcessHost::GetInstance() { + return base::Singleton< + ProfilingProcessHost, + base::LeakySingletonTraits<ProfilingProcessHost>>::get(); } void ProfilingProcessHost::RequestProcessDump(base::ProcessId pid) { - // TODO(brettw) implement process dumping. + if (!connector_) { + LOG(ERROR) + << "Requesting process dump when profiling process hasn't started."; + return; + } + base::PostTaskWithTraits( + FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, + base::BindOnce(&ProfilingProcessHost::GetOutputFileOnBlockingThread, + base::Unretained(this), pid)); +} + +void ProfilingProcessHost::MakeConnector( + content::ServiceManagerConnection* connection) { + connector_ = connection->GetConnector()->Clone(); } void ProfilingProcessHost::LaunchAsService() { // May get called on different threads, we need to be on the IO thread to // work. - // - // TODO(ajwong): This thread bouncing logic is dumb. The - // BindToBrowserConnector() ends up jumping to the UI thread also so this is - // at least 2 bounces. Simplify. if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) { content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO) ->PostTask(FROM_HERE, @@ -97,25 +149,39 @@ return; } - // TODO(ajwong): There's likely a cleaner preexisting connector sitting - // around. See if there's a way to reuse that rather than creating our own? - // - // TODO(ajwong): Dedupe with InitMemlogSenderIfNecessary(). - service_manager::mojom::ConnectorRequest connector_request; - std::unique_ptr<service_manager::Connector> connector = - service_manager::Connector::Create(&connector_request); - - BindToBrowserConnector(std::move(connector_request)); - - mojom::MemlogPtr memlog; - connector->BindInterface(mojom::kServiceName, &memlog); + // Ideally, we'd just call StartProfilingForClient, to interface with the + // memlog client in the current [browser] process, but ChromeContentClient is + // not correctly hooked up for the browser process. The MemlogClient there is + // never bound. Instead, we use the *second* MemlogClient instance in the + // process [a member variable of ProfilingProcessHost], which we also don't + // bind, but instead directly call StartProfiling. + connector_->BindInterface(mojom::kServiceName, &memlog_); mojo::edk::PlatformChannelPair data_channel; - memlog->AddSender( - mojo::WrapPlatformFile(data_channel.PassServerHandle().release().handle), - 0); // 0 is the browser. - StartMemlogSender(base::ScopedPlatformFile( - data_channel.PassClientHandle().release().handle)); + memlog_->AddSender( + base::Process::Current().Pid(), + mojo::WrapPlatformFile(data_channel.PassServerHandle().release().handle)); + memlog_client_.StartProfiling( + mojo::WrapPlatformFile(data_channel.PassClientHandle().release().handle)); +} + +void ProfilingProcessHost::GetOutputFileOnBlockingThread(base::ProcessId pid) { + base::FilePath user_data_dir; + PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); + base::FilePath output_path = user_data_dir.AppendASCII("memlog_dump"); + base::File file(output_path, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&ProfilingProcessHost::HandleDumpProcessOnIOThread, + base::Unretained(this), pid, std::move(file))); +} + +void ProfilingProcessHost::HandleDumpProcessOnIOThread(base::ProcessId pid, + base::File file) { + mojo::ScopedHandle handle = mojo::WrapPlatformFile(file.TakePlatformFile()); + memlog_->DumpProcess(pid, std::move(handle)); } } // namespace profiling
diff --git a/chrome/browser/profiling_host/profiling_process_host.h b/chrome/browser/profiling_host/profiling_process_host.h index daa5b487..ecb7db1 100644 --- a/chrome/browser/profiling_host/profiling_process_host.h +++ b/chrome/browser/profiling_host/profiling_process_host.h
@@ -6,9 +6,18 @@ #define CHROME_BROWSER_PROFILING_HOST_PROFILING_PROCESS_HOST_H_ #include "base/macros.h" +#include "base/memory/singleton.h" #include "base/process/process.h" #include "build/build_config.h" #include "chrome/common/chrome_features.h" +#include "chrome/common/profiling/memlog.mojom.h" +#include "chrome/common/profiling/memlog_client.h" +#include "chrome/common/profiling/memlog_client.mojom.h" +#include "content/public/browser/browser_child_process_observer.h" +#include "content/public/browser/child_process_data.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "services/service_manager/public/cpp/connector.h" // The .mojom include above may not be generated unless OOP heap profiling is // enabled. @@ -16,10 +25,6 @@ #error profiling_process_host.h should only be included with OOP heap profiling #endif -namespace base { -class CommandLine; -} // namespace base - namespace profiling { // Represents the browser side of the profiling process (//chrome/profiling). @@ -39,29 +44,53 @@ // // TODO(ajwong): This host class seems over kill at this point. Can this be // fully subsumed by the ProfilingService class? -class ProfilingProcessHost { +class ProfilingProcessHost : public content::BrowserChildProcessObserver, + content::NotificationObserver { public: // Launches the profiling process if necessary and returns a pointer to it. - static ProfilingProcessHost* EnsureStarted(); + static ProfilingProcessHost* EnsureStarted( + content::ServiceManagerConnection* connection); - // Returns a pointer to the current global profiling process host or, if - // no profiling process is launched, nullptr. - static ProfilingProcessHost* Get(); - - // Appends necessary switches to a command line for a child process so it can - // be profiled. These switches will cause the child process to start in the - // same mode (either profiling or not) as the browser process. - static void AddSwitchesToChildCmdLine(base::CommandLine* child_cmd_line); + // Returns a pointer to the current global profiling process host. + static ProfilingProcessHost* GetInstance(); // Sends a message to the profiling process that it dump the given process' // memory data. void RequestProcessDump(base::ProcessId pid); private: + friend struct base::DefaultSingletonTraits<ProfilingProcessHost>; ProfilingProcessHost(); - ~ProfilingProcessHost(); + ~ProfilingProcessHost() override; + // Make and store a connector from |connection|. + void MakeConnector(content::ServiceManagerConnection* connection); + + // BrowserChildProcessObserver + // Observe connection of non-renderer child processes. + void BrowserChildProcessLaunchedAndConnected( + const content::ChildProcessData& data) override; + + // NotificationObserver + // Observe connection of renderer child processes. + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + // Starts the profiling process. void LaunchAsService(); + void StartProfilingForClient(profiling::mojom::MemlogClientPtr memlog_client, + base::ProcessId pid); + void GetOutputFileOnBlockingThread(base::ProcessId pid); + void HandleDumpProcessOnIOThread(base::ProcessId pid, base::File file); + + content::NotificationRegistrar registrar_; + std::unique_ptr<service_manager::Connector> connector_; + mojom::MemlogPtr memlog_; + + // Handles profiling for the current process, without connecting to any + // service manager interfaces. + profiling::MemlogClient memlog_client_; DISALLOW_COPY_AND_ASSIGN(ProfilingProcessHost); };
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 1360570..d95ce22 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -37,18 +37,6 @@ output_dir = "$root_gen_dir/chrome" } -grit("policy_resources") { - source = "md_policy/policy_resources.grd" - defines = chrome_grit_defines - outputs = [ - "grit/policy_resources.h", - "grit/policy_resources_map.cc", - "grit/policy_resources_map.h", - "policy_resources.pak", - ] - output_dir = "$root_gen_dir/chrome" -} - grit("quota_internals_resources") { source = "quota_internals_resources.grd" defines = chrome_grit_defines
diff --git a/chrome/browser/resources/md_policy/md_policy.html b/chrome/browser/resources/md_policy/md_policy.html deleted file mode 100644 index 0ed7819..0000000 --- a/chrome/browser/resources/md_policy/md_policy.html +++ /dev/null
@@ -1,10 +0,0 @@ -<!doctype html> -<html> -<head> - <meta charset="utf-8"> - <title>Policies</title> -</head> -<body> - <h1>A Material Design policy page is under construction!</h1> -</body> -</html>
diff --git a/chrome/browser/resources/md_policy/policy_resources.grd b/chrome/browser/resources/md_policy/policy_resources.grd deleted file mode 100644 index dc76f52..0000000 --- a/chrome/browser/resources/md_policy/policy_resources.grd +++ /dev/null
@@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> - <outputs> - <output filename="grit/policy_resources.h" type="rc_header"> - <emit emit_type='prepend'></emit> - </output> - <output filename="grit/policy_resources_map.cc" - type="resource_file_map_source" /> - <output filename="grit/policy_resources_map.h" - type="resource_map_header" /> - <output filename="policy_resources.pak" type="data_package" /> - </outputs> - <release seq="1"> - <structures> - <!-- TODO(fhorschig): Add upcoming polymer files here. --> - <structure name="IDR_MD_POLICY_HTML" - file="md_policy.html" - type="chrome_html"/> - </structures> - </release> -</grit>
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index 420b7d6..a4408e4 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -36,6 +36,7 @@ #include "components/grit/components_scaled_resources.h" #include "components/prefs/pref_service.h" #include "content/public/browser/notification_service.h" +#include "extensions/browser/extension_file_task_runner.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" @@ -878,7 +879,7 @@ return; // Write the packed file to disk. - service->GetFileTaskRunner()->PostTask( + extensions::GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::Bind(&WritePackToDiskCallback, base::RetainedRef(pack), extension->path()));
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 98c274a..460e328 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -390,8 +390,6 @@ "webui/password_manager_internals/password_manager_internals_ui.h", "webui/physical_web/physical_web_ui.cc", "webui/physical_web/physical_web_ui.h", - "webui/policy_material_design_ui.cc", - "webui/policy_material_design_ui.h", "webui/policy_ui.cc", "webui/policy_ui.h", "webui/policy_ui_handler.cc",
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc index 90808ed..5cc66f30 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -445,7 +445,8 @@ dialog_->DetachParent(); dialog_ = nullptr; - DCHECK(!callback_.is_null()); + if (callback_.is_null()) + return; // Notify the |callback_| asynchronously because it may need to destroy // DesktopMediaPicker.
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc new file mode 100644 index 0000000..d07f5aff5 --- /dev/null +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc
@@ -0,0 +1,52 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h" + +#include <string> + +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/media/webrtc/desktop_media_list.h" +#include "chrome/browser/media/webrtc/fake_desktop_media_list.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "content/public/browser/desktop_media_id.h" + +class DesktopMediaPickerViewsBrowserTest : public DialogBrowserTest { + public: + DesktopMediaPickerViewsBrowserTest() {} + + // DialogBrowserTest: + void ShowDialog(const std::string& name) override { + picker_ = base::MakeUnique<DesktopMediaPickerViews>(); + auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + gfx::NativeWindow native_window = browser()->window()->GetNativeWindow(); + + std::vector<std::unique_ptr<DesktopMediaList>> source_lists; + for (auto type : {content::DesktopMediaID::TYPE_SCREEN, + content::DesktopMediaID::TYPE_WINDOW, + content::DesktopMediaID::TYPE_WEB_CONTENTS}) { + source_lists.push_back(base::MakeUnique<FakeDesktopMediaList>(type)); + } + + picker_->Show(web_contents, native_window, nullptr, + base::ASCIIToUTF16("app_name"), + base::ASCIIToUTF16("target_name"), std::move(source_lists), + true, DesktopMediaPicker::DoneCallback()); + } + + private: + std::unique_ptr<DesktopMediaPickerViews> picker_; + + DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerViewsBrowserTest); +}; + +// Invokes a dialog that allows the user to select what view of their desktop +// they would like to share. See test_browser_dialog.h. +IN_PROC_BROWSER_TEST_F(DesktopMediaPickerViewsBrowserTest, + InvokeDialog_default) { + RunDialog(); +}
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 3c68998..74a4316 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -34,6 +34,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "components/signin/core/account_id/account_id.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/test/env_test_helper.h" #include "ui/base/hit_test.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/views/widget/widget.h" @@ -113,6 +114,7 @@ } IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) { + aura::test::EnvTestHelper().SetAlwaysUseLastMouseLocation(true); BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); content::WebContents* web_contents = browser_view->GetActiveWebContents(); Widget* widget = browser_view->GetWidget(); @@ -342,6 +344,7 @@ void PreRunTestOnMainThread() override { InProcessBrowserTest::PreRunTestOnMainThread(); + aura::test::EnvTestHelper().SetAlwaysUseLastMouseLocation(true); auto* immersive_mode_controller = browser_view()->immersive_mode_controller(); scoped_observer_.Add(immersive_mode_controller);
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc index 42535dd..a72eb73 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -13,13 +13,14 @@ #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "chrome/test/base/in_process_browser_test.h" -typedef InProcessBrowserTest ZoomBubbleBrowserTest; - #if defined(USE_ASH) #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h" +#include "ui/aura/test/env_test_helper.h" #endif +using ZoomBubbleBrowserTest = InProcessBrowserTest; + // TODO(linux_aura) http://crbug.com/163931 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) #define MAYBE_NonImmersiveFullscreen DISABLED_NonImmersiveFullscreen @@ -72,11 +73,11 @@ } } -// TODO(zturner): Change this to USE_ASH after fixing the test on Windows. #if defined(OS_CHROMEOS) // Test whether the zoom bubble is anchored and whether it is visible when in // immersive fullscreen. IN_PROC_BROWSER_TEST_F(ZoomBubbleBrowserTest, ImmersiveFullscreen) { + aura::test::EnvTestHelper().SetAlwaysUseLastMouseLocation(true); BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); content::WebContents* web_contents = browser_view->GetActiveWebContents();
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 7b94806..7028500 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -46,7 +46,6 @@ #include "chrome/browser/ui/webui/omnibox/omnibox_ui.h" #include "chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.h" #include "chrome/browser/ui/webui/physical_web/physical_web_ui.h" -#include "chrome/browser/ui/webui/policy_material_design_ui.h" #include "chrome/browser/ui/webui/policy_ui.h" #include "chrome/browser/ui/webui/predictors/predictors_ui.h" #include "chrome/browser/ui/webui/profiler_ui.h" @@ -549,10 +548,6 @@ if (url.host_piece() == chrome::kChromeUIPolicyHost) return &NewWebUI<PolicyUI>; - if (url.host_piece() == chrome::kChromeUIMdPolicyHost && - switches::MdPolicyPageEnabled()) { - return &NewWebUI<PolicyMaterialDesignUI>; - } #if BUILDFLAG(ENABLE_APP_LIST) if (url.host_piece() == chrome::kChromeUIAppListStartPageHost)
diff --git a/chrome/browser/ui/webui/memory_internals_ui.cc b/chrome/browser/ui/webui/memory_internals_ui.cc index 2b0130bc..e03b93c 100644 --- a/chrome/browser/ui/webui/memory_internals_ui.cc +++ b/chrome/browser/ui/webui/memory_internals_ui.cc
@@ -9,16 +9,11 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" -#include "base/path_service.h" #include "base/process/process_handle.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/task_scheduler/post_task.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiling_host/profiling_process_host.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/profiling/constants.mojom.h" -#include "chrome/common/profiling/memlog.mojom.h" #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" #include "content/public/browser/browser_child_process_host_iterator.h" @@ -124,12 +119,8 @@ if (!pid_value.is_int()) return; - // TODO(ajwong): Convert from pid to sender_id. https://crbug.com/751283. - - base::PostTaskWithTraits( - FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, - base::BindOnce(&MemoryInternalsDOMHandler::GetOutputFileOnFileThread, - pid_value.GetInt())); + profiling::ProfilingProcessHost::GetInstance()->RequestProcessDump( + pid_value.GetInt()); } void MemoryInternalsDOMHandler::GetChildProcessesOnIOThread( @@ -191,33 +182,6 @@ DisallowJavascript(); } -// static -void MemoryInternalsDOMHandler::GetOutputFileOnFileThread(int32_t sender_id) { - base::FilePath user_data_dir; - PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); - base::FilePath output_path = user_data_dir.AppendASCII("memlog_dump"); - base::File f(output_path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&MemoryInternalsDOMHandler::HandleDumpProcessOnUIThread, - sender_id, std::move(f))); -} - -// static -void MemoryInternalsDOMHandler::HandleDumpProcessOnUIThread(int32_t sender_id, - base::File file) { - profiling::mojom::MemlogPtr memlog; - service_manager::Connector* connector = - content::ServiceManagerConnection::GetForProcess()->GetConnector(); - connector->BindInterface(profiling::mojom::kServiceName, - mojo::MakeRequest(&memlog)); - - mojo::ScopedHandle sh = mojo::WrapPlatformFile(file.TakePlatformFile()); - memlog->DumpProcess(sender_id, std::move(sh)); -} - } // namespace MemoryInternalsUI::MemoryInternalsUI(content::WebUI* web_ui)
diff --git a/chrome/browser/ui/webui/policy_material_design_ui.cc b/chrome/browser/ui/webui/policy_material_design_ui.cc deleted file mode 100644 index d6f0ccc..0000000 --- a/chrome/browser/ui/webui/policy_material_design_ui.cc +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/policy_material_design_ui.h" - -#include <stddef.h> -#include <utility> - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/policy_ui_handler.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/policy_resources.h" -#include "chrome/grit/policy_resources_map.h" -#include "components/policy/core/common/policy_types.h" -#include "components/policy/policy_constants.h" -#include "components/policy/risk_tag.h" -#include "components/strings/grit/components_strings.h" - -namespace { - -// Strings that map from policy::RiskTag enum to i18n string keys and their IDs. -// Their order has to follow the order of the policy::RiskTag enum. -const PolicyStringMap kPolicyRiskTags[policy::RISK_TAG_COUNT] = { - {"fullAdminAccess", IDS_POLICY_RISK_TAG_FULL_ADMIN_ACCESS}, - {"systemSecurity", IDS_POLICY_RISK_TAG_SYSTEM_SECURITY}, - {"websiteSharing", IDS_POLICY_RISK_TAG_WEBSITE_SHARING}, - {"adminSharing", IDS_POLICY_RISK_TAG_ADMIN_SHARING}, - {"filtering", IDS_POLICY_RISK_TAG_FILTERING}, - {"localDataAccess", IDS_POLICY_RISK_TAG_LOCAL_DATA_ACCESS}, - {"googleSharing", IDS_POLICY_RISK_TAG_GOOGLE_SHARING}, -}; - -content::WebUIDataSource* CreatePolicyMaterialDesignUIHtmlSource() { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIMdPolicyHost); - PolicyUIHandler::AddCommonLocalizedStringsToSource(source); - PolicyUIHandler::AddLocalizedPolicyStrings( - source, kPolicyRiskTags, static_cast<size_t>(policy::RISK_TAG_COUNT)); - for (size_t i = 0; i < kPolicyResourcesSize; ++i) { - source->AddResourcePath(kPolicyResources[i].name, - kPolicyResources[i].value); - } - source->SetDefaultResource(IDR_MD_POLICY_HTML); - return source; -} - -} // namespace - -// The JavaScript message handler for the chrome://md-policy page. -class PolicyMaterialDesignUIHandler : public PolicyUIHandler { - public: - PolicyMaterialDesignUIHandler(); - ~PolicyMaterialDesignUIHandler() override; - - protected: - // PolicyUIHandler: - void AddPolicyName(const std::string& name, - base::DictionaryValue* names) const override; - void SendPolicyNames() const override; - - private: - DISALLOW_COPY_AND_ASSIGN(PolicyMaterialDesignUIHandler); -}; - -PolicyMaterialDesignUIHandler::PolicyMaterialDesignUIHandler() { -} - -PolicyMaterialDesignUIHandler::~PolicyMaterialDesignUIHandler() { -} - -void PolicyMaterialDesignUIHandler::AddPolicyName( - const std::string& name, base::DictionaryValue* names) const { - std::unique_ptr<base::ListValue> list(new base::ListValue()); - const policy::RiskTag* tags = policy::GetChromePolicyDetails(name)->risk_tags; - for (size_t i = 0; i < policy::kMaxRiskTagCount; ++i) { - if (tags[i] != policy::RISK_TAG_NONE) - list->AppendString(kPolicyRiskTags[tags[i]].key); - } - names->SetWithoutPathExpansion(name, std::move(list)); -} - -void PolicyMaterialDesignUIHandler::SendPolicyNames() const { - base::ListValue tags; - for (size_t tag = 0; tag < policy::RISK_TAG_COUNT; ++tag) - tags.AppendString(kPolicyRiskTags[tag].key); - - web_ui()->CallJavascriptFunctionUnsafe("policy.Page.setPolicyGroups", tags); - PolicyUIHandler::SendPolicyNames(); -} - -PolicyMaterialDesignUI::PolicyMaterialDesignUI(content::WebUI* web_ui) : - WebUIController(web_ui) { - web_ui->AddMessageHandler(base::MakeUnique<PolicyMaterialDesignUIHandler>()); - content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), - CreatePolicyMaterialDesignUIHtmlSource()); -} - -PolicyMaterialDesignUI::~PolicyMaterialDesignUI() { -}
diff --git a/chrome/browser/ui/webui/policy_material_design_ui.h b/chrome/browser/ui/webui/policy_material_design_ui.h deleted file mode 100644 index ecf7eb1a..0000000 --- a/chrome/browser/ui/webui/policy_material_design_ui.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_WEBUI_POLICY_MATERIAL_DESIGN_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_POLICY_MATERIAL_DESIGN_UI_H_ - -#include "base/macros.h" -#include "content/public/browser/web_ui_controller.h" - -namespace content { -class WebUI; -} - -// The Web UI controller for the chrome://md-policy page. -class PolicyMaterialDesignUI : public content::WebUIController { - public: - explicit PolicyMaterialDesignUI(content::WebUI* web_ui); - ~PolicyMaterialDesignUI() override; - - private: - DISALLOW_COPY_AND_ASSIGN(PolicyMaterialDesignUI); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_POLICY_MATERIAL_DESIGN_UI_H_
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 6bbe0ff..04fc8273 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -95,7 +95,6 @@ "$root_gen_dir/chrome/invalidations_resources.pak", "$root_gen_dir/chrome/net_internals_resources.pak", "$root_gen_dir/chrome/password_manager_internals_resources.pak", - "$root_gen_dir/chrome/policy_resources.pak", "$root_gen_dir/chrome/quota_internals_resources.pak", "$root_gen_dir/chrome/task_scheduler_internals_resources.pak", "$root_gen_dir/chrome/translate_internals_resources.pak", @@ -111,7 +110,6 @@ "//chrome/browser/resources:invalidations_resources", "//chrome/browser/resources:net_internals_resources", "//chrome/browser/resources:password_manager_internals_resources", - "//chrome/browser/resources:policy_resources", "//chrome/browser/resources:quota_internals_resources", "//chrome/browser/resources:task_scheduler_internals_resources", "//chrome/browser/resources:translate_internals_resources",
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index 689653c..a12d095 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc
@@ -55,10 +55,6 @@ #include "url/url_constants.h" #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. -#if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) -#include "chrome/common/profiling/memlog_sender.h" -#endif - #if defined(OS_LINUX) #include <fcntl.h> #include "chrome/common/component_flash_hint_file_linux.h" @@ -718,8 +714,12 @@ void ChromeContentClient::OnServiceManagerConnected( content::ServiceManagerConnection* connection) { #if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) - // MemlogSender depends on ServiceManager to spawn the utility process that - // receives the memory log. - profiling::InitMemlogSenderIfNecessary(connection); + // ChromeContentClient::OnServiceManagerConnected isn't called from the + // browser process or utility processes. This is confusing. :( + // For now, profiling in the the browser process is initialized by + // ChromeBrowserMainParts::ServiceManagerConnectionStarted, and we ignore + // utility processes. + // https://crbug.com/753106. + memlog_client_.OnServiceManagerConnected(connection); #endif // ENABLE_OOP_HEAP_PROFILING }
diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h index df13b08..5e75016b 100644 --- a/chrome/common/chrome_content_client.h +++ b/chrome/common/chrome_content_client.h
@@ -14,6 +14,7 @@ #include "base/files/file_path.h" #include "base/synchronization/lock.h" #include "build/build_config.h" +#include "chrome/common/features.h" #include "chrome/common/origin_trials/chrome_origin_trial_policy.h" #include "content/public/common/content_client.h" #include "ppapi/features/features.h" @@ -22,7 +23,9 @@ #include "content/public/common/pepper_plugin_info.h" #endif -#include "url/url_util.h" +#if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) +#include "chrome/common/profiling/memlog_client.h" +#endif // Returns the user agent of Chrome. std::string GetUserAgent(); @@ -113,6 +116,9 @@ // Used to lock when |origin_trial_policy_| is initialized. base::Lock origin_trial_policy_lock_; std::unique_ptr<ChromeOriginTrialPolicy> origin_trial_policy_; +#if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) + profiling::MemlogClient memlog_client_; +#endif // ENABLE_OOP_HEAP_PROFILING }; #endif // CHROME_COMMON_CHROME_CONTENT_CLIENT_H_
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index db78170..05860e00 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -336,9 +336,6 @@ // Enables the Material Design feedback form. const char kEnableMaterialDesignFeedback[] = "enable-md-feedback"; -// Enables the Material Design policy page at chrome://md-policy. -const char kEnableMaterialDesignPolicyPage[] = "enable-md-policy-page"; - // Runs the Native Client inside the renderer process and enables GPU plugin // (internally adds lEnableGpuPlugin to the command line). const char kEnableNaCl[] = "enable-nacl"; @@ -1060,12 +1057,6 @@ #if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) // Enables the out-of-process memory logging. const char kMemlog[] = "memlog"; - -// Communicates the pipe name for out-of-process memory logging. -const char kMemlogPipe[] = "memlog-pipe"; - -// Value passed to kProcessType switch that indicates the profiling process. -const char kProfiling[] = "profiling"; #endif bool ExtensionsDisabled(const base::CommandLine& command_line) { @@ -1082,11 +1073,6 @@ ::switches::kEnableMaterialDesignFeedback); } -bool MdPolicyPageEnabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kEnableMaterialDesignPolicyPage); -} - #if defined(OS_CHROMEOS) bool PowerOverlayEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 9a68d34c..ca79d202 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -110,7 +110,6 @@ extern const char kEnableExtensionActivityLogTesting[]; extern const char kEnableFastUnload[]; extern const char kEnableMaterialDesignFeedback[]; -extern const char kEnableMaterialDesignPolicyPage[]; extern const char kEnableNaCl[]; extern const char kEnableNavigationTracing[]; extern const char kEnableNetBenchmarking[]; @@ -341,14 +340,11 @@ #if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING) extern const char kMemlog[]; -extern const char kMemlogPipe[]; -extern const char kProfiling[]; #endif bool ExtensionsDisabled(const base::CommandLine& command_line); bool ExtensionsDisabled(); bool MdFeedbackEnabled(); -bool MdPolicyPageEnabled(); #if defined(OS_CHROMEOS) bool PowerOverlayEnabled();
diff --git a/chrome/common/profiling/BUILD.gn b/chrome/common/profiling/BUILD.gn index 421ef32..2cf75a95 100644 --- a/chrome/common/profiling/BUILD.gn +++ b/chrome/common/profiling/BUILD.gn
@@ -10,8 +10,8 @@ sources = [ "memlog_allocator_shim.cc", "memlog_allocator_shim.h", - "memlog_sender.cc", - "memlog_sender.h", + "memlog_client.cc", + "memlog_client.h", "memlog_sender_pipe.h", "memlog_sender_pipe_posix.cc", "memlog_sender_pipe_posix.h", @@ -35,6 +35,10 @@ sources = [ "constants.mojom", "memlog.mojom", + "memlog_client.mojom", + ] + deps = [ + "//mojo/common:common_custom_types", ] } } else {
diff --git a/chrome/common/profiling/memlog.mojom b/chrome/common/profiling/memlog.mojom index f7d48863..eeaeebe 100644 --- a/chrome/common/profiling/memlog.mojom +++ b/chrome/common/profiling/memlog.mojom
@@ -5,19 +5,18 @@ module profiling.mojom; import "mojo/common/file.mojom"; +import "mojo/common/process_id.mojom"; // The profiling process is still in prototype stage, and is behind a // compile-time flag. There will be a security review before removing the // compile-time flag. https://crbug.com/751759. interface Memlog { // Adds a new platform-specific pipe to read memlog trace data from. - // In normal usage, each child process launch will have a corresponding call - // to this. - AddSender(handle sender_pipe, int32 sender_id); + // In normal usage, each child process will be given the other end of this + // pipe. + AddSender(mojo.common.mojom.ProcessId pid, handle sender_pipe); - // Dumps the memory log of the process with the given |sender_id| into - // |output_file|. This currently dumps the memory log of an arbitrary - // process, since there does not yet a mechanism to identify specific - // processes. See https://crbug.com/751283. - DumpProcess(int32 sender_id, handle output_file); + // Dumps the memory log of the process with the given |pid| into + // |output_file|. + DumpProcess(mojo.common.mojom.ProcessId pid, handle output_file); };
diff --git a/chrome/common/profiling/memlog_client.cc b/chrome/common/profiling/memlog_client.cc new file mode 100644 index 0000000..87a2d2e --- /dev/null +++ b/chrome/common/profiling/memlog_client.cc
@@ -0,0 +1,58 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/profiling/memlog_client.h" + +#include "base/files/platform_file.h" +#include "chrome/common/profiling/memlog_allocator_shim.h" +#include "chrome/common/profiling/memlog_sender_pipe.h" +#include "chrome/common/profiling/memlog_stream.h" +#include "content/public/common/service_manager_connection.h" +#include "content/public/common/simple_connection_filter.h" +#include "mojo/public/cpp/system/platform_handle.h" +#include "services/service_manager/public/cpp/binder_registry.h" + +namespace profiling { + +MemlogClient::MemlogClient() = default; + +MemlogClient::~MemlogClient() { + if (connection_) { + connection_->RemoveConnectionFilter(connection_filter_id_); + } +} + +void MemlogClient::OnServiceManagerConnected( + content::ServiceManagerConnection* connection) { + connection_ = connection; + + std::unique_ptr<service_manager::BinderRegistry> registry( + new service_manager::BinderRegistry); + registry->AddInterface(base::Bind(&profiling::MemlogClient::BindToInterface, + base::Unretained(this))); + connection_filter_id_ = connection->AddConnectionFilter( + base::MakeUnique<content::SimpleConnectionFilter>(std::move(registry))); +} + +void MemlogClient::BindToInterface(mojom::MemlogClientRequest request) { + binding_ = std::move(request); +} + +void MemlogClient::StartProfiling(mojo::ScopedHandle sender_pipe) { + base::PlatformFile platform_file; + CHECK_EQ(MOJO_RESULT_OK, + mojo::UnwrapPlatformFile(std::move(sender_pipe), &platform_file)); + + base::ScopedPlatformFile scoped_platform_file(platform_file); + memlog_sender_pipe_.reset( + new MemlogSenderPipe(std::move(scoped_platform_file))); + + StreamHeader header; + header.signature = kStreamSignature; + memlog_sender_pipe_->Send(&header, sizeof(header)); + + InitAllocatorShim(memlog_sender_pipe_.get()); +} + +} // namespace profiling
diff --git a/chrome/common/profiling/memlog_client.h b/chrome/common/profiling/memlog_client.h new file mode 100644 index 0000000..48271a1 --- /dev/null +++ b/chrome/common/profiling/memlog_client.h
@@ -0,0 +1,50 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_PROFILING_MEMLOG_CLIENT_H_ +#define CHROME_COMMON_PROFILING_MEMLOG_CLIENT_H_ + +#include "chrome/common/profiling/memlog_client.mojom.h" +#include "mojo/public/cpp/system/handle.h" + +namespace content { +class ServiceManagerConnection; +} // namespace content + +namespace profiling { + +class MemlogSenderPipe; + +// The MemlogClient listens on the interface for a StartProfiling message. On +// receiving the message, it begins profiling the current process. +// It is also possible to use the MemlogClient to begin profiling the current +// process without connecting to the service manager interface, if the caller +// has a |sender_pipe| to pass to StartProfiling. +class MemlogClient : public mojom::MemlogClient { + public: + MemlogClient(); + ~MemlogClient() override; + + // mojom::MemlogClient overrides: + void StartProfiling(mojo::ScopedHandle sender_pipe) override; + + void OnServiceManagerConnected(content::ServiceManagerConnection* connection); + void BindToInterface(profiling::mojom::MemlogClientRequest request); + + private: + // The most recent MemlogClientRequest is kept alive. + mojom::MemlogClientRequest binding_; + + std::unique_ptr<MemlogSenderPipe> memlog_sender_pipe_; + + // Used to remove the connection filter on destruction. + int connection_filter_id_ = 0; + + // The ServiceManagerConnection must outlive this instance. + content::ServiceManagerConnection* connection_ = nullptr; +}; + +} // namespace profiling + +#endif // CHROME_COMMON_PROFILING_MEMLOG_CLIENT_H_
diff --git a/chrome/common/profiling/memlog_client.mojom b/chrome/common/profiling/memlog_client.mojom new file mode 100644 index 0000000..f3eab396 --- /dev/null +++ b/chrome/common/profiling/memlog_client.mojom
@@ -0,0 +1,15 @@ +// Copyright 2017 The Chromium 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 profiling.mojom; + +// The profiling process is still in prototype stage, and is behind a +// compile-time flag. There will be a security review before removing the +// compile-time flag. https://crbug.com/751759. +interface MemlogClient { + // Start recording allocations and sending them to the profiling process via + // |sender_pipe|. There is currently no mechanism to stop recording + // allocations. + StartProfiling(handle sender_pipe); +};
diff --git a/chrome/common/profiling/memlog_sender.cc b/chrome/common/profiling/memlog_sender.cc deleted file mode 100644 index 4d441fa..0000000 --- a/chrome/common/profiling/memlog_sender.cc +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/common/profiling/memlog_sender.h" - -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "build/build_config.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/profiling/constants.mojom.h" -#include "chrome/common/profiling/memlog.mojom.h" -#include "chrome/common/profiling/memlog_allocator_shim.h" -#include "chrome/common/profiling/memlog_sender_pipe.h" -#include "chrome/common/profiling/memlog_stream.h" -#include "content/public/common/service_manager_connection.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "services/service_manager/public/cpp/connector.h" - -namespace profiling { - -namespace { - -// TODO(brettw) this is a hack to allow StartProfilingMojo to work. Figure out -// how to get the lifetime of this that allows that function call to work. -MemlogSenderPipe* memlog_sender_pipe = nullptr; - -} // namespace - -void InitMemlogSenderIfNecessary( - content::ServiceManagerConnection* connection) { - const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess(); - // TODO(ajwong): Rename to kMemlogId. - std::string pipe_id_str = cmdline.GetSwitchValueASCII(switches::kMemlogPipe); - if (pipe_id_str.empty()) { - return; - } - int sender_id; - CHECK(base::StringToInt(pipe_id_str, &sender_id)); - - // The |memlog| interface is used for a one-shot, no-response, publication - // of the filehandle for the data channel. As such, there is no need to have - // the MemlogPtr live beyond the AddSender() call. - mojom::MemlogPtr memlog; - connection->GetConnector()->BindInterface(profiling::mojom::kServiceName, - &memlog); - - mojo::edk::PlatformChannelPair data_channel; - memlog->AddSender( - mojo::WrapPlatformFile(data_channel.PassServerHandle().release().handle), - sender_id); - StartMemlogSender(base::ScopedPlatformFile( - data_channel.PassClientHandle().release().handle)); -} - -void StartMemlogSender(base::ScopedPlatformFile file) { - static MemlogSenderPipe pipe(std::move(file)); - memlog_sender_pipe = &pipe; - - StreamHeader header; - header.signature = kStreamSignature; - pipe.Send(&header, sizeof(StreamHeader)); - - InitAllocatorShim(&pipe); -} - -void StartProfilingMojo() { - static bool started_mojo = false; - - if (!started_mojo) { - started_mojo = true; - StartMojoControlPacket start_mojo_message; - start_mojo_message.op = kStartMojoControlPacketType; - memlog_sender_pipe->Send(&start_mojo_message, sizeof(start_mojo_message)); - } -} - -} // namespace profiling
diff --git a/chrome/common/profiling/memlog_sender.h b/chrome/common/profiling/memlog_sender.h deleted file mode 100644 index fd276ee..0000000 --- a/chrome/common/profiling/memlog_sender.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_COMMON_PROFILING_MEMLOG_SENDER_H_ -#define CHROME_COMMON_PROFILING_MEMLOG_SENDER_H_ - -#include <string> - -#include "base/files/platform_file.h" -#include "mojo/public/cpp/system/platform_handle.h" - -namespace base { - -class CommandLine; - -} // namespace base - -namespace content { - -class ServiceManagerConnection; - -} // namespace content - -namespace profiling { - -// Starts the memlog sender pipe if the command line has requested it. The pipe -// ID will be extracted from the CommandLine for the process. -void InitMemlogSenderIfNecessary(content::ServiceManagerConnection* connection); - -// Starts the memlog sender pipe with the given ID. -void StartMemlogSender(base::ScopedPlatformFile file); - -// Tells the profiling process to try to connect to the profiling control -// channel. This must be done after the browser is ready to accept such a -// connection. -void StartProfilingMojo(); - -} // namespace profiling - -#endif // CHROME_COMMON_PROFILING_MEMLOG_SENDER_H_
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 7a5c988d..36db417 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -67,7 +67,6 @@ const char kChromeUIInstantURL[] = "chrome://instant/"; const char kChromeUIInterstitialURL[] = "chrome://interstitials/"; const char kChromeUIInvalidationsURL[] = "chrome://invalidations/"; -const char kChromeUIMdPolicyURL[] = "chrome://md-policy/"; const char kChromeUINaClURL[] = "chrome://nacl/"; const char kChromeUINetInternalsURL[] = "chrome://net-internals/"; const char kChromeUINewProfileURL[] = "chrome://newprofile/"; @@ -219,7 +218,6 @@ const char kChromeUIKillHost[] = "kill"; const char kChromeUILargeIconHost[] = "large-icon"; const char kChromeUILocalStateHost[] = "local-state"; -const char kChromeUIMdPolicyHost[] = "md-policy"; const char kChromeUIMediaEngagementHost[] = "media-engagement"; const char kChromeUINaClHost[] = "nacl"; const char kChromeUINetExportHost[] = "net-export";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index dea320d..f8c25f3 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -61,7 +61,6 @@ extern const char kChromeUIInstantURL[]; extern const char kChromeUIInterstitialURL[]; extern const char kChromeUIInvalidationsURL[]; -extern const char kChromeUIMdPolicyURL[]; extern const char kChromeUIMediaEngagementHost[]; extern const char kChromeUINaClURL[]; extern const char kChromeUINetInternalsURL[]; @@ -208,7 +207,6 @@ extern const char kChromeUIKillHost[]; extern const char kChromeUILargeIconHost[]; extern const char kChromeUILocalStateHost[]; -extern const char kChromeUIMdPolicyHost[]; extern const char kChromeUINaClHost[]; extern const char kChromeUINetExportHost[]; extern const char kChromeUINetInternalsHost[];
diff --git a/chrome/installer/zucchini/BUILD.gn b/chrome/installer/zucchini/BUILD.gn index 008406c3..cc00facf 100644 --- a/chrome/installer/zucchini/BUILD.gn +++ b/chrome/installer/zucchini/BUILD.gn
@@ -41,6 +41,8 @@ "type_win_pe.h", "typed_value.h", "zucchini.h", + "zucchini_apply.cc", + "zucchini_gen.cc", ] deps = [
diff --git a/chrome/installer/zucchini/buffer_view.h b/chrome/installer/zucchini/buffer_view.h index 08ca499a..7c41ba6 100644 --- a/chrome/installer/zucchini/buffer_view.h +++ b/chrome/installer/zucchini/buffer_view.h
@@ -51,6 +51,9 @@ : first_(first), last_(first_ + size) { DCHECK_GE(last_, first_); } + template <class U> + explicit BufferViewBase(const BufferViewBase<U>& that) + : first_(that.begin()), last_(that.end()) {} BufferViewBase(const BufferViewBase&) = default; BufferViewBase& operator=(const BufferViewBase&) = default;
diff --git a/chrome/installer/zucchini/main_utils.cc b/chrome/installer/zucchini/main_utils.cc index f11c0223..c80e74e 100644 --- a/chrome/installer/zucchini/main_utils.cc +++ b/chrome/installer/zucchini/main_utils.cc
@@ -51,7 +51,7 @@ /******** List of Zucchini commands ********/ constexpr Command kCommands[] = { - {"gen", "-gen <old_file> <new_file> <patch_file>", 3, &MainGen}, + {"gen", "-gen <old_file> <new_file> <patch_file> [-raw]", 3, &MainGen}, {"apply", "-apply <old_file> <patch_file> <new_file>", 3, &MainApply}, {"crc32", "-crc32 <file>", 1, &MainCrc32}, };
diff --git a/chrome/installer/zucchini/zucchini.h b/chrome/installer/zucchini/zucchini.h index 411180bc..a21b8095 100644 --- a/chrome/installer/zucchini/zucchini.h +++ b/chrome/installer/zucchini/zucchini.h
@@ -5,6 +5,10 @@ #ifndef CHROME_INSTALLER_ZUCCHINI_ZUCCHINI_H_ #define CHROME_INSTALLER_ZUCCHINI_ZUCCHINI_H_ +#include "chrome/installer/zucchini/buffer_view.h" +#include "chrome/installer/zucchini/patch_reader.h" +#include "chrome/installer/zucchini/patch_writer.h" + // Definitions, structures, and interfaces for the Zucchini library. namespace zucchini { @@ -18,10 +22,32 @@ kStatusInvalidParam = 1, kStatusFileReadError = 2, kStatusFileWriteError = 3, + kStatusPatchReadError = 4, + kStatusPatchWriteError = 5, + kStatusInvalidOldImage = 6, + kStatusInvalidNewImage = 7, }; } // namespace status +// Generates ensemble patch from |old_image| to |new_image|, and writes it to +// |patch_writer|. +status::Code GenerateEnsemble(ConstBufferView old_image, + ConstBufferView new_image, + EnsemblePatchWriter* patch_writer); + +// Generates raw patch from |old_image| to |new_image|, and writes it to +// |patch_writer|. +status::Code GenerateRaw(ConstBufferView old_image, + ConstBufferView new_image, + EnsemblePatchWriter* patch_writer); + +// Applies |patch_reader| to |old_image| to build |new_image|, which refers to +// preallocated memory of sufficient size. +status::Code Apply(ConstBufferView old_image, + const EnsemblePatchReader& patch_reader, + MutableBufferView new_image); + } // namespace zucchini #endif // CHROME_INSTALLER_ZUCCHINI_ZUCCHINI_H_
diff --git a/chrome/installer/zucchini/zucchini_apply.cc b/chrome/installer/zucchini/zucchini_apply.cc new file mode 100644 index 0000000..95f8af8 --- /dev/null +++ b/chrome/installer/zucchini/zucchini_apply.cc
@@ -0,0 +1,27 @@ +// Copyright 2017 The Chromium Authors. 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/installer/zucchini/zucchini.h" + +namespace zucchini { + +status::Code Apply(ConstBufferView old_image, + const EnsemblePatchReader& patch_reader, + MutableBufferView new_image) { + if (!patch_reader.CheckOldFile(old_image)) { + LOG(ERROR) << "Invalid old_image."; + return zucchini::status::kStatusInvalidOldImage; + } + + // TODO(etiennep): Implement. + + // This will always fail for now, because of missing implementation. + if (!patch_reader.CheckNewFile(ConstBufferView(new_image))) { + LOG(ERROR) << "Invalid new_image."; + return zucchini::status::kStatusInvalidNewImage; + } + return zucchini::status::kStatusSuccess; +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/zucchini_commands.cc b/chrome/installer/zucchini/zucchini_commands.cc index be3bb34..1447f41b 100644 --- a/chrome/installer/zucchini/zucchini_commands.cc +++ b/chrome/installer/zucchini/zucchini_commands.cc
@@ -16,6 +16,8 @@ #include "chrome/installer/zucchini/buffer_view.h" #include "chrome/installer/zucchini/crc32.h" #include "chrome/installer/zucchini/io_utils.h" +#include "chrome/installer/zucchini/patch_reader.h" +#include "chrome/installer/zucchini/patch_writer.h" namespace { @@ -68,6 +70,10 @@ DISALLOW_COPY_AND_ASSIGN(MappedFileWriter); }; +/******** Command-line Switches ********/ + +const char kSwitchRaw[] = "raw"; + } // namespace zucchini::status::Code MainGen(MainParams params) { @@ -79,13 +85,26 @@ if (!new_image.is_ok()) return zucchini::status::kStatusFileReadError; - // TODO(etiennep): Implement. + zucchini::EnsemblePatchWriter patch_writer(old_image.region(), + new_image.region()); - // Dummy output as placeholder. - MappedFileWriter patch(params.file_paths[2], 256); + auto generate = params.command_line.HasSwitch(kSwitchRaw) + ? zucchini::GenerateRaw + : zucchini::GenerateEnsemble; + zucchini::status::Code status = + generate(old_image.region(), new_image.region(), &patch_writer); + if (status != zucchini::status::kStatusSuccess) { + params.out << "Fatal error encountered when generating patch." << std::endl; + return status; + } + + MappedFileWriter patch(params.file_paths[2], patch_writer.SerializedSize()); if (!patch.is_ok()) return zucchini::status::kStatusFileWriteError; + if (!patch_writer.SerializeInto(patch.region())) + return zucchini::status::kStatusPatchWriteError; + return zucchini::status::kStatusSuccess; } @@ -98,13 +117,23 @@ if (!patch.is_ok()) return zucchini::status::kStatusFileReadError; - // TODO(etiennep): Implement. + auto patch_reader = zucchini::EnsemblePatchReader::Create(patch.region()); + if (!patch_reader.has_value()) { + params.err << "Error reading patch header." << std::endl; + return zucchini::status::kStatusPatchReadError; + } + zucchini::PatchHeader header = patch_reader->header(); - // Dummy output as placeholder. - MappedFileWriter new_image(params.file_paths[2], 256); + MappedFileWriter new_image(params.file_paths[2], header.new_size); if (!new_image.is_ok()) return zucchini::status::kStatusFileWriteError; + zucchini::status::Code status = + zucchini::Apply(old_image.region(), *patch_reader, new_image.region()); + if (status != zucchini::status::kStatusSuccess) { + params.err << "Fatal error encountered while applying patch." << std::endl; + return status; + } return zucchini::status::kStatusSuccess; }
diff --git a/chrome/installer/zucchini/zucchini_gen.cc b/chrome/installer/zucchini/zucchini_gen.cc new file mode 100644 index 0000000..a3685f8 --- /dev/null +++ b/chrome/installer/zucchini/zucchini_gen.cc
@@ -0,0 +1,46 @@ +// Copyright 2017 The Chromium Authors. 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/installer/zucchini/image_utils.h" +#include "chrome/installer/zucchini/zucchini.h" + +namespace zucchini { + +status::Code GenerateEnsemble(ConstBufferView old_image, + ConstBufferView new_image, + EnsemblePatchWriter* patch_writer) { + patch_writer->SetPatchType(PatchType::kEnsemblePatch); + + // Dummy patch element to fill patch_writer. + PatchElementWriter patch_element( + {Element(old_image.region()), Element(new_image.region())}); + patch_element.SetEquivalenceSink({}); + patch_element.SetExtraDataSink({}); + patch_element.SetRawDeltaSink({}); + patch_element.SetReferenceDeltaSink({}); + patch_writer->AddElement(std::move(patch_element)); + + // TODO(etiennep): Implement. + return zucchini::status::kStatusSuccess; +} + +status::Code GenerateRaw(ConstBufferView old_image, + ConstBufferView new_image, + EnsemblePatchWriter* patch_writer) { + patch_writer->SetPatchType(PatchType::kRawPatch); + + // Dummy patch element to fill patch_writer. + PatchElementWriter patch_element( + {Element(old_image.region()), Element(new_image.region())}); + patch_element.SetEquivalenceSink({}); + patch_element.SetExtraDataSink({}); + patch_element.SetRawDeltaSink({}); + patch_element.SetReferenceDeltaSink({}); + patch_writer->AddElement(std::move(patch_element)); + + // TODO(etiennep): Implement. + return zucchini::status::kStatusSuccess; +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/zucchini_main.cc b/chrome/installer/zucchini/zucchini_main.cc index 3791890..170e814 100644 --- a/chrome/installer/zucchini/zucchini_main.cc +++ b/chrome/installer/zucchini/zucchini_main.cc
@@ -44,6 +44,9 @@ *base::CommandLine::ForCurrentProcess(); InitLogging(); InitErrorHandling(command_line); - return static_cast<int>( - RunZucchiniCommand(command_line, std::cout, std::cerr)); + zucchini::status::Code status = + RunZucchiniCommand(command_line, std::cout, std::cerr); + if (status != zucchini::status::kStatusSuccess) + std::cerr << "Failed with code " << static_cast<int>(status) << std::endl; + return static_cast<int>(status); }
diff --git a/chrome/profiling/memlog_connection_manager.cc b/chrome/profiling/memlog_connection_manager.cc index b801ccd..f1e5d70 100644 --- a/chrome/profiling/memlog_connection_manager.cc +++ b/chrome/profiling/memlog_connection_manager.cc
@@ -18,9 +18,9 @@ struct MemlogConnectionManager::Connection { Connection(AllocationTracker::CompleteCallback complete_cb, BacktraceStorage* backtrace_storage, - int sender_id, + base::ProcessId pid, scoped_refptr<MemlogReceiverPipe> p) - : thread(base::StringPrintf("Sender %d thread", sender_id)), + : thread(base::StringPrintf("Sender %d thread", pid)), pipe(p), tracker(std::move(complete_cb), backtrace_storage) {} @@ -45,36 +45,35 @@ MemlogConnectionManager::~MemlogConnectionManager() {} void MemlogConnectionManager::OnNewConnection(base::ScopedPlatformFile file, - int sender_id) { + base::ProcessId pid) { base::AutoLock l(connections_lock_); - DCHECK(connections_.find(sender_id) == connections_.end()); + DCHECK(connections_.find(pid) == connections_.end()); scoped_refptr<MemlogReceiverPipe> new_pipe = new MemlogReceiverPipe(std::move(file)); // Task to post to clean up the connection. Don't need to retain |this| since // it wil be called by objects owned by the MemlogConnectionManager. - AllocationTracker::CompleteCallback complete_cb = - base::BindOnce(&MemlogConnectionManager::OnConnectionCompleteThunk, - base::Unretained(this), - base::MessageLoop::current()->task_runner(), sender_id); + AllocationTracker::CompleteCallback complete_cb = base::BindOnce( + &MemlogConnectionManager::OnConnectionCompleteThunk, + base::Unretained(this), base::MessageLoop::current()->task_runner(), pid); std::unique_ptr<Connection> connection = base::MakeUnique<Connection>( - std::move(complete_cb), backtrace_storage_, sender_id, new_pipe); + std::move(complete_cb), backtrace_storage_, pid, new_pipe); connection->thread.Start(); connection->parser = new MemlogStreamParser(&connection->tracker); new_pipe->SetReceiver(connection->thread.task_runner(), connection->parser); - connections_[sender_id] = std::move(connection); + connections_[pid] = std::move(connection); io_runner_->PostTask( FROM_HERE, base::Bind(&MemlogReceiverPipe::StartReadingOnIOThread, new_pipe)); } -void MemlogConnectionManager::OnConnectionComplete(int sender_id) { +void MemlogConnectionManager::OnConnectionComplete(base::ProcessId pid) { base::AutoLock l(connections_lock_); - auto found = connections_.find(sender_id); + auto found = connections_.find(pid); CHECK(found != connections_.end()); found->second.release(); connections_.erase(found); @@ -83,24 +82,19 @@ // Posts back to the given thread the connection complete message. void MemlogConnectionManager::OnConnectionCompleteThunk( scoped_refptr<base::SingleThreadTaskRunner> main_loop, - int sender_id) { + base::ProcessId pid) { // This code is called by the allocation tracker which is owned by the // connection manager. When we tell the connection manager a connection is // done, we know the conncetion manager will still be in scope. main_loop->PostTask(FROM_HERE, base::Bind(&MemlogConnectionManager::OnConnectionComplete, - base::Unretained(this), sender_id)); + base::Unretained(this), pid)); } -void MemlogConnectionManager::DumpProcess(int32_t sender_id, +void MemlogConnectionManager::DumpProcess(base::ProcessId pid, base::File output_file) { base::AutoLock l(connections_lock_); - if (connections_.empty()) { - LOG(ERROR) << "No connections found for memory dump."; - return; - } - // Lock all connections to prevent deallocations of atoms from // BacktraceStorage. This only works if no new connections are made, which // connections_lock_ guarantees. @@ -111,13 +105,16 @@ base::MakeUnique<base::AutoLock>(*connection->parser->GetLock())); } - // Pick the first connection, since there's no way to identify connections - // right now. https://crbug.com/751283. - Connection* connection = connections_.begin()->second.get(); + auto it = connections_.find(pid); + if (it == connections_.end()) { + LOG(ERROR) << "No connections found for memory dump for pid:" << pid; + return; + } + + Connection* connection = it->second.get(); std::ostringstream oss; - ExportAllocationEventSetToJSON(sender_id, connection->tracker.live_allocs(), - oss); + ExportAllocationEventSetToJSON(pid, connection->tracker.live_allocs(), oss); std::string reply = oss.str(); output_file.WriteAtCurrentPos(reply.c_str(), reply.size()); }
diff --git a/chrome/profiling/memlog_connection_manager.h b/chrome/profiling/memlog_connection_manager.h index 9c6afb3..4339d0f 100644 --- a/chrome/profiling/memlog_connection_manager.h +++ b/chrome/profiling/memlog_connection_manager.h
@@ -11,6 +11,7 @@ #include "base/files/file.h" #include "base/files/platform_file.h" #include "base/macros.h" +#include "base/process/process_handle.h" #include "base/synchronization/lock.h" #include "build/build_config.h" #include "chrome/profiling/backtrace_storage.h" @@ -36,9 +37,9 @@ ~MemlogConnectionManager(); // Dumps the memory log for the given process into |output_file|. - void DumpProcess(int32_t sender_id, base::File output_file); + void DumpProcess(base::ProcessId pid, base::File output_file); - void OnNewConnection(base::ScopedPlatformFile file, int sender_id); + void OnNewConnection(base::ScopedPlatformFile file, base::ProcessId pid); private: struct Connection; @@ -47,17 +48,17 @@ // is signaled by the pipe server, this is signaled by the allocation tracker // to ensure that the pipeline for this process has been flushed of all // messages. - void OnConnectionComplete(int sender_id); + void OnConnectionComplete(base::ProcessId pid); void OnConnectionCompleteThunk( scoped_refptr<base::SingleThreadTaskRunner> main_loop, - int process_id); + base::ProcessId process_id); scoped_refptr<base::SequencedTaskRunner> io_runner_; BacktraceStorage* backtrace_storage_; // Not owned. // Maps process ID to the connection information for it. - base::flat_map<int, std::unique_ptr<Connection>> connections_; + base::flat_map<base::ProcessId, std::unique_ptr<Connection>> connections_; base::Lock connections_lock_; DISALLOW_COPY_AND_ASSIGN(MemlogConnectionManager);
diff --git a/chrome/profiling/memlog_impl.cc b/chrome/profiling/memlog_impl.cc index 5d83a99..8b61c672 100644 --- a/chrome/profiling/memlog_impl.cc +++ b/chrome/profiling/memlog_impl.cc
@@ -18,7 +18,8 @@ MemlogImpl::~MemlogImpl() {} -void MemlogImpl::AddSender(mojo::ScopedHandle sender_pipe, int32_t sender_id) { +void MemlogImpl::AddSender(base::ProcessId pid, + mojo::ScopedHandle sender_pipe) { base::PlatformFile platform_file; CHECK_EQ(MOJO_RESULT_OK, mojo::UnwrapPlatformFile(std::move(sender_pipe), &platform_file)); @@ -26,13 +27,12 @@ // MemlogConnectionManager is deleted on the IOThread thus using // base::Unretained() is safe here. io_runner_->PostTask( - FROM_HERE, - base::BindOnce(&MemlogConnectionManager::OnNewConnection, - base::Unretained(connection_manager_.get()), - base::ScopedPlatformFile(platform_file), sender_id)); + FROM_HERE, base::BindOnce(&MemlogConnectionManager::OnNewConnection, + base::Unretained(connection_manager_.get()), + base::ScopedPlatformFile(platform_file), pid)); } -void MemlogImpl::DumpProcess(int32_t sender_id, +void MemlogImpl::DumpProcess(base::ProcessId pid, mojo::ScopedHandle output_file) { base::PlatformFile platform_file; MojoResult result = @@ -45,7 +45,7 @@ io_runner_->PostTask( FROM_HERE, base::BindOnce(&MemlogConnectionManager::DumpProcess, base::Unretained(connection_manager_.get()), - sender_id, std::move(file))); + pid, std::move(file))); } } // namespace profiling
diff --git a/chrome/profiling/memlog_impl.h b/chrome/profiling/memlog_impl.h index bd033c612..50cafa7 100644 --- a/chrome/profiling/memlog_impl.h +++ b/chrome/profiling/memlog_impl.h
@@ -27,8 +27,9 @@ MemlogImpl(); ~MemlogImpl() override; - void AddSender(mojo::ScopedHandle sender_pipe, int32_t sender_id) override; - void DumpProcess(int32_t sender_id, mojo::ScopedHandle output_file) override; + void AddSender(base::ProcessId pid, mojo::ScopedHandle sender_pipe) override; + void DumpProcess(base::ProcessId pid, + mojo::ScopedHandle output_file) override; private: // Helper for managing lifetime of MemlogConnectionManager.
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index d9e3cea..eaf33c7d 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -122,6 +122,7 @@ #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" +#include "third_party/WebKit/public/platform/scheduler/renderer_process_type.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" @@ -288,12 +289,14 @@ SpellCheckReplacer::~SpellCheckReplacer() = default; #endif -#if BUILDFLAG(ENABLE_EXTENSIONS) bool IsStandaloneExtensionProcess() { +#if !BUILDFLAG(ENABLE_EXTENSIONS) + return false; +#else return base::CommandLine::ForCurrentProcess()->HasSwitch( extensions::switches::kExtensionProcess); -} #endif +} // Defers media player loading in background pages until they're visible. // TODO(dalecurtis): Include an idle listener too. http://crbug.com/509135 @@ -387,6 +390,11 @@ void ChromeContentRendererClient::RenderThreadStarted() { RenderThread* thread = RenderThread::Get(); + thread->SetRendererProcessType( + IsStandaloneExtensionProcess() + ? blink::scheduler::RendererProcessType::kExtensionRenderer + : blink::scheduler::RendererProcessType::kRenderer); + { startup_metric_utils::mojom::StartupMetricHostPtr startup_metric_host; thread->GetConnector()->BindInterface(content::mojom::kBrowserServiceName, @@ -1183,11 +1191,7 @@ } bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() { -#if BUILDFLAG(ENABLE_EXTENSIONS) return !IsStandaloneExtensionProcess(); -#else - return true; -#endif } bool ChromeContentRendererClient::AllowStoppingTimersWhenProcessBackgrounded() { @@ -1417,11 +1421,7 @@ // TODO(nick): https://crbug.com/268640 Gather stats for extension processes // too; we would need to check the extension's manifest to know which sites // it's allowed to access. -#if BUILDFLAG(ENABLE_EXTENSIONS) return !IsStandaloneExtensionProcess(); -#else - return true; -#endif } std::unique_ptr<blink::WebContentSettingsClient> @@ -1584,11 +1584,7 @@ // information. Also, the enforcement of sending and binding UDP is already done // by chrome extension permission model. bool ChromeContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() { -#if BUILDFLAG(ENABLE_EXTENSIONS) return !IsStandaloneExtensionProcess(); -#else - return true; -#endif } GURL ChromeContentRendererClient::OverrideFlashEmbedWithHTML(const GURL& url) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 4429362..94fd01a 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2310,7 +2310,6 @@ "../browser/chromeos/policy/user_policy_test_helper.cc", "../browser/chromeos/policy/user_policy_test_helper.h", "../browser/chromeos/policy/variations_service_policy_browsertest.cc", - "../browser/chromeos/power/peripheral_battery_observer_browsertest.cc", "../browser/chromeos/preferences_chromeos_browsertest.cc", "../browser/chromeos/profiles/profile_helper_browsertest.cc", "../browser/chromeos/shutdown_policy_browsertest.cc", @@ -2662,6 +2661,7 @@ } if (use_aura) { + sources += [ "../browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc" ] if (enable_wifi_display) { sources += [ "../../extensions/browser/api/display_source/display_source_apitestbase.cc", @@ -5014,7 +5014,7 @@ inputs = [ script, shell_script, - "data/safe_browsing/dmg/make_hfs.sh", + "data/safe_browsing/dmg/hfs_raw_images.tar.bz2", "data/safe_browsing/mach_o/executablefat", "data/safe_browsing/mach_o/lib64.dylib", ]
diff --git a/chrome/test/data/safe_browsing/dmg/.gitignore b/chrome/test/data/safe_browsing/dmg/.gitignore new file mode 100644 index 0000000..d7b4bd6 --- /dev/null +++ b/chrome/test/data/safe_browsing/dmg/.gitignore
@@ -0,0 +1,2 @@ +hfs_plus.img +hfsx_case_sensitive.img
diff --git a/chrome/test/data/safe_browsing/dmg/Makefile b/chrome/test/data/safe_browsing/dmg/Makefile new file mode 100644 index 0000000..935b64e --- /dev/null +++ b/chrome/test/data/safe_browsing/dmg/Makefile
@@ -0,0 +1,17 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +hfs_raw_images.tar.bz2: hfs_plus.img hfsx_case_sensitive.img + tar cjf $@ $^ + +MAKE_HFS=./make_hfs.sh + +hfs_plus.img: $(MAKE_HFS) + rm -f $@ + $(MAKE_HFS) HFS+ 1024 $@ + +hfsx_case_sensitive.img: $(MAKE_HFS) + rm -f $@ + # 8*1024 = 8192 + $(MAKE_HFS) hfsx 8192 $@
diff --git a/chrome/test/data/safe_browsing/dmg/README.md b/chrome/test/data/safe_browsing/dmg/README.md new file mode 100644 index 0000000..6d5e8ad3 --- /dev/null +++ b/chrome/test/data/safe_browsing/dmg/README.md
@@ -0,0 +1,13 @@ +# Safe Browsing DMG Test Data + +This directory contains scripts to generate test DMG and HFS files for +unit-testing the Safe Browsing archive scanner. The contents of this directory +are primarily used by `//chrome/test:mac_safe_browsing_test_data`. + +Most of the data are generated at build-time using the `generate_test_data.sh` +script. However, due to a [macOS issue](https://crbug.com/696529) the outputs +from the `make_hfs.sh` script are generated independently and checked-in. + +These independently generated data are stored in `hfs_raw_images.tar.bz2` and +can be regenerated using the `Makefile` in this directory. The build system +will extract the archive into the build output directory.
diff --git a/chrome/test/data/safe_browsing/dmg/generate_test_data.sh b/chrome/test/data/safe_browsing/dmg/generate_test_data.sh index cbb266fa..df85c7b 100755 --- a/chrome/test/data/safe_browsing/dmg/generate_test_data.sh +++ b/chrome/test/data/safe_browsing/dmg/generate_test_data.sh
@@ -30,9 +30,9 @@ # HFS Raw Images ############################################################# - MAKE_HFS="${THIS_DIR}/make_hfs.sh" - "${MAKE_HFS}" HFS+ 1024 "${OUT_DIR}/hfs_plus.img" - "${MAKE_HFS}" hfsx $((8 * 1024)) "${OUT_DIR}/hfsx_case_sensitive.img" + # Extract the checked-in testdata to the OUT_DIR, ignoring the archived + # modification times. + tar x -m -C "${OUT_DIR}" -f "${THIS_DIR}/hfs_raw_images.tar.bz2" # DMG Files ################################################################## @@ -93,7 +93,7 @@ # Overwrites 'koly' with '????'. printf '\xa1\xa1\xa1\xa1' | dd conv=notrunc \ of="${OUT_DIR}/mach_o_in_dmg_no_koly_signature.dmg" \ - bs=1 seek=$(($SIZE - 512)) + bs=1 seek=$(($SIZE - 512)) &> /dev/null # Copy of Mach-O DMG with extension changed to .txt. cp "${OUT_DIR}/mach_o_in_dmg.dmg" "${OUT_DIR}/mach_o_in_dmg.txt"
diff --git a/chrome/test/data/safe_browsing/dmg/hfs_raw_images.tar.bz2 b/chrome/test/data/safe_browsing/dmg/hfs_raw_images.tar.bz2 new file mode 100644 index 0000000..85ed0b1 --- /dev/null +++ b/chrome/test/data/safe_browsing/dmg/hfs_raw_images.tar.bz2 Binary files differ
diff --git a/chrome/test/data/safe_browsing/dmg/make_hfs.sh b/chrome/test/data/safe_browsing/dmg/make_hfs.sh index 0de6c360..4287ee4 100755 --- a/chrome/test/data/safe_browsing/dmg/make_hfs.sh +++ b/chrome/test/data/safe_browsing/dmg/make_hfs.sh
@@ -33,10 +33,6 @@ RAMDISK_VOLUME=$(hdiutil attach -nomount ram://$RAMDISK_SIZE) diskutil erasevolume "${FILESYSTEM_TYPE}" "${VOLUME_NAME}" ${RAMDISK_VOLUME} ->&2 echo "Temporary debugging for crbug.com/696529." ->&2 diskutil list ->&2 hdiutil pmap -complete -debug ${RAMDISK_VOLUME} ->&2 echo "RAMDISK_VOLUME: " + ${RAMDISK_VOLUME} diskutil mount ${RAMDISK_VOLUME} pushd "/Volumes/${VOLUME_NAME}"
diff --git a/chromeos/components/tether/host_scanner.cc b/chromeos/components/tether/host_scanner.cc index b4736dae..570b6ba 100644 --- a/chromeos/components/tether/host_scanner.cc +++ b/chromeos/components/tether/host_scanner.cc
@@ -39,7 +39,6 @@ device_id_tether_network_guid_map_(device_id_tether_network_guid_map), host_scan_cache_(host_scan_cache), clock_(clock), - is_fetching_hosts_(false), weak_ptr_factory_(this) {} HostScanner::~HostScanner() {} @@ -99,6 +98,8 @@ // notification. notification_presenter_->NotifyMultiplePotentialHotspotsNearby(); } + + was_available_hotspot_notification_shown_ = true; } if (is_final_scan_result) { @@ -167,7 +168,10 @@ } if (final_scan_results.empty()) { - RecordHostScanResult(HostScanResultEventType::NOTIFICATION_NOT_SHOWN); + RecordHostScanResult(HostScanResultEventType::NO_HOSTS_FOUND); + } else if (!was_available_hotspot_notification_shown_) { + RecordHostScanResult( + HostScanResultEventType::HOSTS_FOUND_BUT_NO_NOTIFICATION_SHOWN); } else if (final_scan_results.size() == 1u) { RecordHostScanResult( HostScanResultEventType::NOTIFICATION_SHOWN_SINGLE_HOST); @@ -175,6 +179,7 @@ RecordHostScanResult( HostScanResultEventType::NOTIFICATION_SHOWN_MULTIPLE_HOSTS); } + was_available_hotspot_notification_shown_ = false; // If the final scan result has been received, the operation is finished. // Delete it.
diff --git a/chromeos/components/tether/host_scanner.h b/chromeos/components/tether/host_scanner.h index a162f35..d2ef16f7 100644 --- a/chromeos/components/tether/host_scanner.h +++ b/chromeos/components/tether/host_scanner.h
@@ -77,9 +77,10 @@ FRIEND_TEST_ALL_PREFIXES(HostScannerTest, TestScan_ResultsFromNoDevices); enum HostScanResultEventType { - NOTIFICATION_NOT_SHOWN = 0, + NO_HOSTS_FOUND = 0, NOTIFICATION_SHOWN_SINGLE_HOST = 1, NOTIFICATION_SHOWN_MULTIPLE_HOSTS = 2, + HOSTS_FOUND_BUT_NO_NOTIFICATION_SHOWN = 3, HOST_SCAN_RESULT_MAX }; @@ -100,7 +101,8 @@ HostScanCache* host_scan_cache_; base::Clock* clock_; - bool is_fetching_hosts_; + bool is_fetching_hosts_ = false; + bool was_available_hotspot_notification_shown_ = false; std::unique_ptr<HostScannerOperation> host_scanner_operation_; std::unordered_set<std::string> tether_guids_in_cache_before_scan_;
diff --git a/chromeos/components/tether/host_scanner_unittest.cc b/chromeos/components/tether/host_scanner_unittest.cc index 4254a028..98f47776 100644 --- a/chromeos/components/tether/host_scanner_unittest.cc +++ b/chromeos/components/tether/host_scanner_unittest.cc
@@ -283,8 +283,12 @@ if (is_final_scan_result) { HostScanner::HostScanResultEventType expected_event_type = - HostScanner::HostScanResultEventType::NOTIFICATION_NOT_SHOWN; - if (scanned_device_infos_from_current_scan_.size() == 1) { + HostScanner::HostScanResultEventType::NO_HOSTS_FOUND; + if (!scanned_device_infos_from_current_scan_.empty() && + is_connected_to_internet) { + expected_event_type = HostScanner::HostScanResultEventType:: + HOSTS_FOUND_BUT_NO_NOTIFICATION_SHOWN; + } else if (scanned_device_infos_from_current_scan_.size() == 1) { expected_event_type = HostScanner::HostScanResultEventType:: NOTIFICATION_SHOWN_SINGLE_HOST; } else if (scanned_device_infos_from_current_scan_.size() > 1) { @@ -495,7 +499,7 @@ histogram_tester_.ExpectUniqueSample( "InstantTethering.HostScanResult", - HostScanner::HostScanResultEventType::NOTIFICATION_NOT_SHOWN, 1); + HostScanner::HostScanResultEventType::NO_HOSTS_FOUND, 1); } TEST_F(HostScannerTest, TestScan_ResultsFromSomeDevices) {
diff --git a/components/arc/common/file_system.mojom b/components/arc/common/file_system.mojom index aa45972..698cf6f5 100644 --- a/components/arc/common/file_system.mojom +++ b/components/arc/common/file_system.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Next MinVersion: 5 +// Next MinVersion: 6 module arc.mojom; @@ -27,6 +27,12 @@ // TODO(crbug.com/672737): Use mojo.common.mojom.Time once the type is // converted to a non-native type so that it can be used from Java. uint64 last_modified; + + // Path to a real file on the Android VFS corresponding to this document, + // e.g. "/storage/emulated/0/DCIM/kitten.jpg". + // This value is available in limited DocumentsProviders only. If the + // provider does not expose real VFS paths, this field is always set to null. + [MinVersion=5] string? android_file_system_path; }; // Describes the type of a change made to a document. @@ -51,7 +57,7 @@ [MinVersion=3] OnDocumentChanged@0(int64 watcher_id, ChangeType type); }; -// Next method ID: 9 +// Next method ID: 10 interface FileSystemInstance { // Notes about Android Documents Provider: // @@ -62,8 +68,11 @@ // It is the origin part of a content:// URI used to access the Documents // Provider via Content Resolver protocol. // Example: "com.android.providers.media.documents" + // - A documents provider may provide one or more roots. Each root is identified + // by a root ID. // - A document ID is an opaque string that specifies a particular document - // in a documents provider. Its format varies by providers. + // in a documents provider. Its format varies by providers. Roots also have + // associated document IDs. // // See the following documents for details about Documents Provider: // https://developer.android.com/guide/topics/providers/document-provider.html @@ -109,6 +118,12 @@ // URL. When an error occurs, returns null value. [MinVersion=4] GetMimeType@8(string url) => (string? mime_type); + // Queries recent documents of a root specified by |authority| and |root_id|. + // If the root exists and it supports recent document queries, a (possibly + // empty) list of documents is returned. Otherwise, null is returned. + [MinVersion=5] GetRecentDocuments@9(string authority, string root_id) => + (array<Document>? documents); + // Establishes full-duplex communication with the host. [MinVersion=3] Init@5(FileSystemHost host_ptr);
diff --git a/components/arc/test/fake_file_system_instance.cc b/components/arc/test/fake_file_system_instance.cc index fdb4e78..1ada10b 100644 --- a/components/arc/test/fake_file_system_instance.cc +++ b/components/arc/test/fake_file_system_instance.cc
@@ -250,6 +250,15 @@ base::Passed(base::make_optional(std::move(children))))); } +void FakeFileSystemInstance::GetRecentDocuments( + const std::string& authority, + const std::string& root_id, + const GetRecentDocumentsCallback& callback) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, base::nullopt)); +} + void FakeFileSystemInstance::Init(mojom::FileSystemHostPtr host) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(host);
diff --git a/components/arc/test/fake_file_system_instance.h b/components/arc/test/fake_file_system_instance.h index 8e0d4a5..9192d9e 100644 --- a/components/arc/test/fake_file_system_instance.h +++ b/components/arc/test/fake_file_system_instance.h
@@ -36,6 +36,7 @@ // Documents provider based functions are: // - GetDocument() // - GetChildDocuments() +// - GetRecentDocuments() // Fake documents for those functions can be set up by AddDocument(). // // Notes: @@ -139,6 +140,9 @@ const GetFileSizeCallback& callback) override; void GetMimeType(const std::string& url, const GetMimeTypeCallback& callback) override; + void GetRecentDocuments(const std::string& authority, + const std::string& root_id, + const GetRecentDocumentsCallback& callback) override; void Init(mojom::FileSystemHostPtr host) override; void OpenFileToRead(const std::string& url, const OpenFileToReadCallback& callback) override;
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java index ece02e1..9f87219 100644 --- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java +++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
@@ -55,13 +55,9 @@ /** * @return whether query autofill suggestion. */ - // TODO(michaelbai): Change it to abstract after DEP roll. - public boolean shouldQueryAutofillSuggestion() { - return false; - } + public abstract boolean shouldQueryAutofillSuggestion(); - // TODO(michaelbai): Change it to abstract after DEP roll. - public void queryAutofillSuggestion() {} + public abstract void queryAutofillSuggestion(); /** * Invoked when filling form is need. AutofillProvider shall ask autofill
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc index 03f7473..99214549 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.cc +++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -45,6 +45,7 @@ #include "components/sync_bookmarks/bookmark_change_processor.h" #include "components/sync_bookmarks/bookmark_data_type_controller.h" #include "components/sync_bookmarks/bookmark_model_associator.h" +#include "components/sync_bookmarks/bookmark_model_type_controller.h" #include "components/sync_sessions/session_data_type_controller.h" #include "google_apis/gaia/oauth2_token_service.h" #include "google_apis/gaia/oauth2_token_service_request.h" @@ -204,9 +205,14 @@ // Bookmark sync is enabled by default. Register unless explicitly // disabled. if (!disabled_types.Has(syncer::BOOKMARKS)) { - sync_service->RegisterDataTypeController( - base::MakeUnique<BookmarkDataTypeController>(error_callback, - sync_client_)); + if (FeatureList::IsEnabled(switches::kSyncUSSBookmarks)) { + sync_service->RegisterDataTypeController( + base::MakeUnique<sync_bookmarks::BookmarkModelTypeController>()); + } else { + sync_service->RegisterDataTypeController( + base::MakeUnique<BookmarkDataTypeController>(error_callback, + sync_client_)); + } } // These features are enabled only if history is not disabled.
diff --git a/components/offline_pages/core/offline_page_model.h b/components/offline_pages/core/offline_page_model.h index ee5fba6..c7b89426 100644 --- a/components/offline_pages/core/offline_page_model.h +++ b/components/offline_pages/core/offline_page_model.h
@@ -44,15 +44,6 @@ // * how to cancel requests and what to expect class OfflinePageModel : public base::SupportsUserData { public: - // Controls how to search on differnt URLs for pages. - enum class URLSearchMode { - // Match against the last committed URL only. - SEARCH_BY_FINAL_URL_ONLY, - // Match against all stored URLs, including the last committed URL and - // the original request URL. - SEARCH_BY_ALL_URLS - }; - // Describes the parameters to control how to save a page. struct SavePageParams { SavePageParams();
diff --git a/components/offline_pages/core/offline_page_model_impl.cc b/components/offline_pages/core/offline_page_model_impl.cc index c6ee5cab..5a973ee 100644 --- a/components/offline_pages/core/offline_page_model_impl.cc +++ b/components/offline_pages/core/offline_page_model_impl.cc
@@ -561,7 +561,9 @@ OfflinePageModelQueryBuilder builder; builder .SetUrls(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING, - std::vector<GURL>(urls.begin(), urls.end())) + std::vector<GURL>(urls.begin(), urls.end()), + URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, + false /* strip_fragment */) .RequireRestrictedToOriginalTab( OfflinePageModelQueryBuilder::Requirement::EXCLUDE_MATCHING); auto pages_to_urls = base::Bind( @@ -648,43 +650,14 @@ const GURL& url, URLSearchMode url_search_mode, const MultipleOfflinePageItemCallback& callback) { + OfflinePageModelQueryBuilder builder; + builder.SetUrls(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING, + std::vector<GURL>({url}), url_search_mode, + true /* strip_fragment */); RunWhenLoaded( - base::Bind(&OfflinePageModelImpl::GetPagesByURLWhenLoadDone, - weak_ptr_factory_.GetWeakPtr(), url, - url_search_mode, callback)); -} - -void OfflinePageModelImpl::GetPagesByURLWhenLoadDone( - const GURL& url, - URLSearchMode url_search_mode, - const MultipleOfflinePageItemCallback& callback) const { - DCHECK(is_loaded_); - std::vector<OfflinePageItem> result; - - GURL::Replacements remove_params; - remove_params.ClearRef(); - - GURL url_without_fragment = - url.ReplaceComponents(remove_params); - - for (const auto& id_page_pair : offline_pages_) { - // First, search by last committed URL with fragment stripped. - if (url_without_fragment == - id_page_pair.second.url.ReplaceComponents(remove_params)) { - result.push_back(id_page_pair.second); - continue; - } - // Then, search by original request URL if |url_search_mode| wants it. - // Note that we want to do the exact match with fragment included. This is - // because original URL is used for redirect purpose and it is always safer - // to support the exact redirect. - if (url_search_mode == URLSearchMode::SEARCH_BY_ALL_URLS && - url == id_page_pair.second.original_url) { - result.push_back(id_page_pair.second); - } - } - - callback.Run(result); + base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(builder.Build(GetPolicyController())), callback)); } void OfflinePageModelImpl::CheckMetadataConsistency() {
diff --git a/components/offline_pages/core/offline_page_model_impl_unittest.cc b/components/offline_pages/core/offline_page_model_impl_unittest.cc index 89b7432c..bc78dd5 100644 --- a/components/offline_pages/core/offline_page_model_impl_unittest.cc +++ b/components/offline_pages/core/offline_page_model_impl_unittest.cc
@@ -527,8 +527,7 @@ const GURL& url) { MultipleOfflinePageItemResult result; model()->GetPagesByURL( - url, - OfflinePageModel::URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, + url, URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult, AsWeakPtr(), base::Unretained(&result))); PumpLoop(); @@ -539,8 +538,7 @@ const GURL& url) { MultipleOfflinePageItemResult result; model()->GetPagesByURL( - url, - OfflinePageModel::URLSearchMode::SEARCH_BY_ALL_URLS, + url, URLSearchMode::SEARCH_BY_ALL_URLS, base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult, AsWeakPtr(), base::Unretained(&result))); PumpLoop();
diff --git a/components/offline_pages/core/offline_page_model_query.cc b/components/offline_pages/core/offline_page_model_query.cc index 382e20b..2f87756 100644 --- a/components/offline_pages/core/offline_page_model_query.cc +++ b/components/offline_pages/core/offline_page_model_query.cc
@@ -11,8 +11,45 @@ namespace offline_pages { +namespace { + +int CountMatchingUrls(const GURL& url_pattern, + const std::set<GURL>& urls, + bool strip_fragment) { + int count = 0; + + // If |strip_fragment| is true, all urls will be compared after fragments + // stripped. Otherwise just do exact matching. + if (strip_fragment) { + for (const auto& url : urls) { + GURL::Replacements remove_params; + remove_params.ClearRef(); + GURL url_without_fragment = url.ReplaceComponents(remove_params); + if (url_without_fragment == url_pattern.ReplaceComponents(remove_params)) + count++; + } + } else { + count = urls.count(url_pattern); + } + return count; +} + +} // namespace + using Requirement = OfflinePageModelQuery::Requirement; +OfflinePageModelQuery::URLSearchParams::URLSearchParams() = default; + +OfflinePageModelQuery::URLSearchParams::URLSearchParams( + std::set<GURL> url_set, + URLSearchMode search_mode, + bool strip_frag) + : urls(url_set), mode(search_mode), strip_fragment(strip_frag) {} + +OfflinePageModelQuery::URLSearchParams::URLSearchParams( + const URLSearchParams& params) = default; +OfflinePageModelQuery::URLSearchParams::~URLSearchParams() = default; + OfflinePageModelQueryBuilder::OfflinePageModelQueryBuilder() : offline_ids_(std::make_pair(Requirement::UNSET, std::vector<int64_t>())) { } @@ -35,8 +72,13 @@ OfflinePageModelQueryBuilder& OfflinePageModelQueryBuilder::SetUrls( Requirement requirement, - const std::vector<GURL>& urls) { - urls_ = std::make_pair(requirement, urls); + const std::vector<GURL>& urls, + URLSearchMode search_mode, + bool defrag) { + urls_ = std::make_pair( + requirement, + OfflinePageModelQuery::URLSearchParams( + std::set<GURL>(urls.begin(), urls.end()), search_mode, defrag)); return *this; } @@ -80,9 +122,11 @@ auto query = base::MakeUnique<OfflinePageModelQuery>(); - query->urls_ = std::make_pair( - urls_.first, std::set<GURL>(urls_.second.begin(), urls_.second.end())); - urls_ = std::make_pair(Requirement::UNSET, std::vector<GURL>()); + query->urls_ = urls_; + urls_ = std::make_pair( + Requirement::UNSET, + OfflinePageModelQuery::URLSearchParams( + std::set<GURL>(), URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false)); query->offline_ids_ = std::make_pair( offline_ids_.first, std::set<int64_t>(offline_ids_.second.begin(), offline_ids_.second.end())); @@ -176,11 +220,15 @@ return client_ids_; } -std::pair<Requirement, std::set<GURL>> +std::pair<Requirement, OfflinePageModelQuery::URLSearchParams> OfflinePageModelQuery::GetRestrictedToUrls() const { - if (urls_.first == Requirement::UNSET) - return std::make_pair(Requirement::UNSET, std::set<GURL>()); - + if (std::get<0>(urls_) == Requirement::UNSET) { + URLSearchParams unset_params; + unset_params.urls = std::set<GURL>(); + unset_params.mode = URLSearchMode::SEARCH_BY_FINAL_URL_ONLY; + unset_params.strip_fragment = false; + return std::make_pair(Requirement::UNSET, unset_params); + } return urls_; } @@ -198,17 +246,17 @@ break; } - switch (urls_.first) { - case Requirement::UNSET: - break; - case Requirement::INCLUDE_MATCHING: - if (urls_.second.count(item.url) == 0) - return false; - break; - case Requirement::EXCLUDE_MATCHING: - if (urls_.second.count(item.url) > 0) - return false; - break; + Requirement url_requirement = urls_.first; + URLSearchParams params = urls_.second; + if (url_requirement != Requirement::UNSET) { + int count = CountMatchingUrls(item.url, params.urls, params.strip_fragment); + if (params.mode == URLSearchMode::SEARCH_BY_ALL_URLS) + count += CountMatchingUrls(item.original_url, params.urls, + false /* strip_fragment */); + if ((url_requirement == Requirement::INCLUDE_MATCHING && count == 0) || + (url_requirement == Requirement::EXCLUDE_MATCHING && count > 0)) { + return false; + } } const ClientId& client_id = item.client_id;
diff --git a/components/offline_pages/core/offline_page_model_query.h b/components/offline_pages/core/offline_page_model_query.h index 4107b39..8378b0ef 100644 --- a/components/offline_pages/core/offline_page_model_query.h +++ b/components/offline_pages/core/offline_page_model_query.h
@@ -32,13 +32,33 @@ EXCLUDE_MATCHING, }; + struct URLSearchParams { + URLSearchParams(); + URLSearchParams(const URLSearchParams& params); + URLSearchParams(std::set<GURL> url_set, + URLSearchMode search_mode, + bool strip_frag); + ~URLSearchParams(); + + // The set of urls for matching. + std::set<GURL> urls; + // The mode for searching. By final url only or both final and original + // urls. + URLSearchMode mode; + // Whether fragments should be stripped. It will *not* work on + // *|original_url|*. + // TODO(crbug.com/753609): Try to make this also available when matching for + // |original_url|. + bool strip_fragment; + }; + OfflinePageModelQuery(); virtual ~OfflinePageModelQuery(); std::pair<bool, std::set<std::string>> GetRestrictedToNamespaces() const; std::pair<Requirement, std::set<int64_t>> GetRestrictedToOfflineIds() const; std::pair<Requirement, std::set<ClientId>> GetRestrictedToClientIds() const; - std::pair<Requirement, std::set<GURL>> GetRestrictedToUrls() const; + std::pair<Requirement, URLSearchParams> GetRestrictedToUrls() const; // This is the workhorse function that is used by the in-memory offline page // model, given a page it will find out whether that page matches the query. @@ -51,7 +71,7 @@ std::pair<Requirement, std::set<int64_t>> offline_ids_; std::pair<Requirement, std::set<ClientId>> client_ids_; - std::pair<Requirement, std::set<GURL>> urls_; + std::pair<Requirement, URLSearchParams> urls_; DISALLOW_COPY_AND_ASSIGN(OfflinePageModelQuery); }; @@ -82,8 +102,16 @@ // Sets the URLs that are valid for this request. If called multiple times, // overwrites previous URL restrictions. + // |search_mode| is used to control if the URL will be matched with final + // URL only or both final URL and original URL. + // If |strip_fragment| is true, *only final* urls will be matched without + // fragment. + // TODO(crbug.com/753609): Try to unify fragment handling for original and + // final urls. OfflinePageModelQueryBuilder& SetUrls(Requirement requirement, - const std::vector<GURL>& urls); + const std::vector<GURL>& urls, + URLSearchMode search_mode, + bool strip_fragment); // Only include pages whose namespaces satisfy // ClientPolicyController::IsRemovedOnCacheReset(|namespace|) == @@ -131,7 +159,7 @@ std::pair<Requirement, std::vector<int64_t>> offline_ids_; std::pair<Requirement, std::vector<ClientId>> client_ids_; - std::pair<Requirement, std::vector<GURL>> urls_; + std::pair<Requirement, OfflinePageModelQuery::URLSearchParams> urls_; Requirement removed_on_cache_reset_ = Requirement::UNSET; Requirement supported_by_download_ = Requirement::UNSET;
diff --git a/components/offline_pages/core/offline_page_model_query_unittest.cc b/components/offline_pages/core/offline_page_model_query_unittest.cc index 01eb27b6a..d3d90b5 100644 --- a/components/offline_pages/core/offline_page_model_query_unittest.cc +++ b/components/offline_pages/core/offline_page_model_query_unittest.cc
@@ -14,6 +14,7 @@ namespace offline_pages { using Requirement = OfflinePageModelQueryBuilder::Requirement; +using URLSearchParams = OfflinePageModelQuery::URLSearchParams; namespace { @@ -26,6 +27,9 @@ const OfflinePageItem kTestItem2(kUrl2, 2, kClientId2, base::FilePath(), 2); const char kTestNamespace[] = "test_namespace"; +const GURL kTempUrl = GURL("https://temp.temp"); +const GURL kTempFragUrl = GURL("https://temp.temp#frag1"); +const GURL kFragUrl1 = GURL("https://ktestitem1.com#frag"); } // namespace class OfflinePageModelQueryTest : public testing::Test { @@ -60,6 +64,14 @@ return OfflinePageItem(GURL("https://download.com"), 7, {kLastNNamespace, "id1"}, base::FilePath(), 7); } + + const OfflinePageItem CreatePageWithUrls(const GURL& url, + const GURL& original_url) { + OfflinePageItem page = kTestItem1; + page.url = url; + page.original_url = original_url; + return page; + } }; OfflinePageModelQueryTest::OfflinePageModelQueryTest() { @@ -215,67 +227,85 @@ TEST_F(OfflinePageModelQueryTest, UrlsSet) { std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; - builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls); + builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false); std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); auto restriction = query->GetRestrictedToUrls(); const Requirement& requirement = restriction.first; - const std::set<GURL>& urls_out = restriction.second; + const URLSearchParams& params = restriction.second; EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode); + EXPECT_FALSE(params.strip_fragment); - ASSERT_EQ(urls.size(), urls_out.size()); + ASSERT_EQ(urls.size(), params.urls.size()); for (auto url : urls) { - EXPECT_EQ(1U, urls_out.count(url)) << "Did not find " << url - << "in query restrictions."; + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; } EXPECT_TRUE(query->Matches(kTestItem1)); EXPECT_FALSE(query->Matches(kTestItem2)); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl))); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(GURL(""), GURL("https://abc.def")))); } TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude) { std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; - builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls); + builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false); std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); auto restriction = query->GetRestrictedToUrls(); const Requirement& requirement = restriction.first; - const std::set<GURL>& urls_out = restriction.second; + const URLSearchParams& params = restriction.second; EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode); + EXPECT_FALSE(params.strip_fragment); - ASSERT_EQ(urls.size(), urls_out.size()); + ASSERT_EQ(urls.size(), params.urls.size()); for (auto url : urls) { - EXPECT_EQ(1U, urls_out.count(url)) << "Did not find " << url - << "in query restrictions."; + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; } EXPECT_FALSE(query->Matches(kTestItem1)); EXPECT_TRUE(query->Matches(kTestItem2)); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl))); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(GURL(""), GURL("https://abc.def")))); } TEST_F(OfflinePageModelQueryTest, UrlsReplace) { std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; std::vector<GURL> urls2 = {kUrl2, GURL("https://abc.def")}; - builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls); - builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls2); + builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false); + builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls2, + URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false); std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); auto restriction = query->GetRestrictedToUrls(); const Requirement& requirement = restriction.first; - const std::set<GURL>& urls_out = restriction.second; + const URLSearchParams& params = restriction.second; EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode); + EXPECT_FALSE(params.strip_fragment); - ASSERT_EQ(urls2.size(), urls_out.size()); + ASSERT_EQ(urls2.size(), params.urls.size()); for (auto url : urls2) { - EXPECT_EQ(1U, urls_out.count(url)) << "Did not find " << url - << "in query restrictions."; + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; } EXPECT_FALSE(query->Matches(kTestItem1)); @@ -452,4 +482,210 @@ EXPECT_FALSE(query->Matches(test_namespace_page())); } +TEST_F(OfflinePageModelQueryTest, UrlsSet_SearchByAll) { + std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; + builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_ALL_URLS, false); + + std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); + + auto restriction = query->GetRestrictedToUrls(); + const Requirement& requirement = restriction.first; + const URLSearchParams& params = restriction.second; + + EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode); + EXPECT_FALSE(params.strip_fragment); + + ASSERT_EQ(urls.size(), params.urls.size()); + for (auto url : urls) { + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; + } + + EXPECT_TRUE(query->Matches(kTestItem1)); + EXPECT_FALSE(query->Matches(kTestItem2)); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl))); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(kUrl1, GURL("https://abc.def")))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def")))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL("")))); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, GURL("")))); +} + +TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude_SearchByAll) { + std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; + builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_ALL_URLS, false); + + std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); + + auto restriction = query->GetRestrictedToUrls(); + const Requirement& requirement = restriction.first; + const URLSearchParams& params = restriction.second; + + EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode); + EXPECT_FALSE(params.strip_fragment); + + ASSERT_EQ(urls.size(), params.urls.size()); + for (auto url : urls) { + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; + } + + EXPECT_FALSE(query->Matches(kTestItem1)); + EXPECT_TRUE(query->Matches(kTestItem2)); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl))); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(kUrl1, GURL("https://abc.def")))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def")))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL("")))); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, GURL("")))); +} + +TEST_F(OfflinePageModelQueryTest, UrlsSet_Defrag) { + std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; + builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, true); + + std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); + + auto restriction = query->GetRestrictedToUrls(); + const Requirement& requirement = restriction.first; + const URLSearchParams& params = restriction.second; + + EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode); + EXPECT_TRUE(params.strip_fragment); + + ASSERT_EQ(urls.size(), params.urls.size()); + for (auto url : urls) { + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; + } + + EXPECT_TRUE(query->Matches(kTestItem1)); + EXPECT_FALSE(query->Matches(kTestItem2)); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempUrl))); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(kFragUrl1, GURL("https://abc.def")))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def")))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL("")))); + EXPECT_TRUE(query->Matches( + CreatePageWithUrls(GURL("https://abc.def#frag2"), GURL("")))); +} + +TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude_Defrag) { + std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; + builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, true); + + std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); + + auto restriction = query->GetRestrictedToUrls(); + const Requirement& requirement = restriction.first; + const URLSearchParams& params = restriction.second; + + EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode); + EXPECT_TRUE(params.strip_fragment); + + ASSERT_EQ(urls.size(), params.urls.size()); + for (auto url : urls) { + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; + } + + EXPECT_FALSE(query->Matches(kTestItem1)); + EXPECT_TRUE(query->Matches(kTestItem2)); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempUrl))); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(kFragUrl1, GURL("https://abc.def")))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def")))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL("")))); + EXPECT_FALSE(query->Matches( + CreatePageWithUrls(GURL("https://abc.def#frag2"), GURL("")))); +} + +TEST_F(OfflinePageModelQueryTest, UrlsSet_SearchByAll_Defrag) { + std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; + builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_ALL_URLS, true); + + std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); + + auto restriction = query->GetRestrictedToUrls(); + const Requirement& requirement = restriction.first; + const URLSearchParams& params = restriction.second; + + EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode); + EXPECT_TRUE(params.strip_fragment); + + ASSERT_EQ(urls.size(), params.urls.size()); + for (auto url : urls) { + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; + } + + EXPECT_TRUE(query->Matches(kTestItem1)); + EXPECT_FALSE(query->Matches(kTestItem2)); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempUrl))); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kFragUrl1))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(kFragUrl1, GURL("https://abc.def")))); + EXPECT_FALSE(query->Matches( + CreatePageWithUrls(kTempUrl, GURL("https://abc.def#frag2")))); + EXPECT_TRUE( + query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL("")))); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempFragUrl, GURL("")))); +} + +TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude_SearchByAll_Defrag) { + std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")}; + builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls, + URLSearchMode::SEARCH_BY_ALL_URLS, true); + + std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_); + + auto restriction = query->GetRestrictedToUrls(); + const Requirement& requirement = restriction.first; + const URLSearchParams& params = restriction.second; + + EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement); + EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode); + EXPECT_TRUE(params.strip_fragment); + + ASSERT_EQ(urls.size(), params.urls.size()); + for (auto url : urls) { + EXPECT_EQ(1U, params.urls.count(url)) + << "Did not find " << url << "in query restrictions."; + } + + EXPECT_FALSE(query->Matches(kTestItem1)); + EXPECT_TRUE(query->Matches(kTestItem2)); + EXPECT_FALSE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempFragUrl))); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kFragUrl1))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(kUrl1, GURL("https://abc.def#frag2")))); + EXPECT_TRUE(query->Matches( + CreatePageWithUrls(kTempUrl, GURL("https://abc.def#frag2")))); + EXPECT_FALSE( + query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL("")))); + EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempFragUrl, GURL("")))); +} + } // namespace offline_pages
diff --git a/components/offline_pages/core/offline_page_types.h b/components/offline_pages/core/offline_page_types.h index 552b32a..34dfc84 100644 --- a/components/offline_pages/core/offline_page_types.h +++ b/components/offline_pages/core/offline_page_types.h
@@ -72,6 +72,15 @@ RESULT_COUNT, }; +// Controls how to search on differnt URLs for pages. +enum class URLSearchMode { + // Match against the last committed URL only. + SEARCH_BY_FINAL_URL_ONLY, + // Match against all stored URLs, including the last committed URL and + // the original request URL. + SEARCH_BY_ALL_URLS, +}; + typedef std::set<GURL> CheckPagesExistOfflineResult; typedef std::vector<int64_t> MultipleOfflineIdResult; typedef std::vector<OfflinePageItem> MultipleOfflinePageItemResult;
diff --git a/components/sync/driver/async_directory_type_controller.cc b/components/sync/driver/async_directory_type_controller.cc index 51576a6..af25444 100644 --- a/components/sync/driver/async_directory_type_controller.cc +++ b/components/sync/driver/async_directory_type_controller.cc
@@ -144,11 +144,6 @@ state_ = NOT_RUNNING; } -std::string AsyncDirectoryTypeController::name() const { - // For logging only. - return ModelTypeToString(type()); -} - DataTypeController::State AsyncDirectoryTypeController::state() const { return state_; }
diff --git a/components/sync/driver/async_directory_type_controller.h b/components/sync/driver/async_directory_type_controller.h index 90e2975..1ac3f5b 100644 --- a/components/sync/driver/async_directory_type_controller.h +++ b/components/sync/driver/async_directory_type_controller.h
@@ -39,7 +39,6 @@ void StartAssociating(const StartCallback& start_callback) override; void Stop() override; ChangeProcessor* GetChangeProcessor() const override; - std::string name() const override; State state() const override; // Used by tests to override the factory used to create
diff --git a/components/sync/driver/data_type_controller.h b/components/sync/driver/data_type_controller.h index 8fd7bd8..473f7827 100644 --- a/components/sync/driver/data_type_controller.h +++ b/components/sync/driver/data_type_controller.h
@@ -137,7 +137,7 @@ virtual void Stop() = 0; // Name of this data type. For logging purposes only. - virtual std::string name() const = 0; + std::string name() const { return ModelTypeToString(type()); } // Current state of the data type controller. virtual State state() const = 0;
diff --git a/components/sync/driver/fake_data_type_controller.cc b/components/sync/driver/fake_data_type_controller.cc index de640d19..660f2e3e 100644 --- a/components/sync/driver/fake_data_type_controller.cc +++ b/components/sync/driver/fake_data_type_controller.cc
@@ -112,10 +112,6 @@ state_ = NOT_RUNNING; } -std::string FakeDataTypeController::name() const { - return ModelTypeToString(type()); -} - ChangeProcessor* FakeDataTypeController::GetChangeProcessor() const { return nullptr; }
diff --git a/components/sync/driver/fake_data_type_controller.h b/components/sync/driver/fake_data_type_controller.h index 5add35c6..43de65a 100644 --- a/components/sync/driver/fake_data_type_controller.h +++ b/components/sync/driver/fake_data_type_controller.h
@@ -34,7 +34,6 @@ ModelTypeConfigurer* configurer) override; void StartAssociating(const StartCallback& start_callback) override; void Stop() override; - std::string name() const override; ChangeProcessor* GetChangeProcessor() const override; State state() const override; bool ReadyForStart() const override;
diff --git a/components/sync/driver/frontend_data_type_controller.cc b/components/sync/driver/frontend_data_type_controller.cc index 1bf2c18..c68abb2 100644 --- a/components/sync/driver/frontend_data_type_controller.cc +++ b/components/sync/driver/frontend_data_type_controller.cc
@@ -106,11 +106,6 @@ state_ = NOT_RUNNING; } -std::string FrontendDataTypeController::name() const { - // For logging only. - return ModelTypeToString(type()); -} - DataTypeController::State FrontendDataTypeController::state() const { return state_; }
diff --git a/components/sync/driver/frontend_data_type_controller.h b/components/sync/driver/frontend_data_type_controller.h index a873b2c..69b61aa 100644 --- a/components/sync/driver/frontend_data_type_controller.h +++ b/components/sync/driver/frontend_data_type_controller.h
@@ -46,7 +46,6 @@ void LoadModels(const ModelLoadCallback& model_load_callback) override; void StartAssociating(const StartCallback& start_callback) override; void Stop() override; - std::string name() const override; State state() const override; protected:
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc index 69f56b9..a55b5977 100644 --- a/components/sync/driver/model_type_controller.cc +++ b/components/sync/driver/model_type_controller.cc
@@ -217,11 +217,6 @@ state_ = NOT_RUNNING; } -std::string ModelTypeController::name() const { - // For logging only. - return ModelTypeToString(type()); -} - DataTypeController::State ModelTypeController::state() const { return state_; }
diff --git a/components/sync/driver/model_type_controller.h b/components/sync/driver/model_type_controller.h index 496c418..203f3bc 100644 --- a/components/sync/driver/model_type_controller.h +++ b/components/sync/driver/model_type_controller.h
@@ -46,7 +46,6 @@ void ActivateDataType(ModelTypeConfigurer* configurer) override; void DeactivateDataType(ModelTypeConfigurer* configurer) override; void Stop() override; - std::string name() const override; State state() const override; void GetAllNodes(const AllNodesCallback& callback) override; void GetStatusCounters(const StatusCountersCallback& callback) override;
diff --git a/components/sync/driver/proxy_data_type_controller.cc b/components/sync/driver/proxy_data_type_controller.cc index 837145b..2a0e29d 100644 --- a/components/sync/driver/proxy_data_type_controller.cc +++ b/components/sync/driver/proxy_data_type_controller.cc
@@ -58,11 +58,6 @@ state_ = NOT_RUNNING; } -std::string ProxyDataTypeController::name() const { - // For logging only. - return ModelTypeToString(type()); -} - DataTypeController::State ProxyDataTypeController::state() const { return state_; }
diff --git a/components/sync/driver/proxy_data_type_controller.h b/components/sync/driver/proxy_data_type_controller.h index 93b3c13..661c093 100644 --- a/components/sync/driver/proxy_data_type_controller.h +++ b/components/sync/driver/proxy_data_type_controller.h
@@ -29,7 +29,6 @@ ModelTypeConfigurer* configurer) override; void StartAssociating(const StartCallback& start_callback) override; void Stop() override; - std::string name() const override; State state() const override; void ActivateDataType(ModelTypeConfigurer* configurer) override; void DeactivateDataType(ModelTypeConfigurer* configurer) override;
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc index 5e745ac..a0e74ef5 100644 --- a/components/sync/driver/sync_driver_switches.cc +++ b/components/sync/driver/sync_driver_switches.cc
@@ -53,6 +53,10 @@ const base::Feature kSyncUSSAutocomplete{"SyncUSSAutocomplete", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enable USS implementation of Bookmarks datatype. +const base::Feature kSyncUSSBookmarks{"SyncUSSBookmarks", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables USS implementation of DeviceInfo datatype. This flag controls whether // SyncableService based or ModelTypeSyncBridge based implementation is used for // DeviceInfo type.
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h index bce16be..8b2f121 100644 --- a/components/sync/driver/sync_driver_switches.h +++ b/components/sync/driver/sync_driver_switches.h
@@ -24,8 +24,9 @@ extern const base::Feature kSyncUserLanguageDetectionEvents; extern const base::Feature kSyncUserTranslationEvents; extern const base::Feature kSyncUSSAutocomplete; -extern const base::Feature kSyncUSSTypedURL; +extern const base::Feature kSyncUSSBookmarks; extern const base::Feature kSyncUSSDeviceInfo; +extern const base::Feature kSyncUSSTypedURL; } // namespace switches
diff --git a/components/sync_bookmarks/BUILD.gn b/components/sync_bookmarks/BUILD.gn index e283f687..2cc8268 100644 --- a/components/sync_bookmarks/BUILD.gn +++ b/components/sync_bookmarks/BUILD.gn
@@ -12,6 +12,10 @@ "bookmark_data_type_controller.h", "bookmark_model_associator.cc", "bookmark_model_associator.h", + "bookmark_model_type_controller.cc", + "bookmark_model_type_controller.h", + "bookmark_model_type_processor.cc", + "bookmark_model_type_processor.h", ] deps = [ @@ -30,6 +34,7 @@ sources = [ "bookmark_data_type_controller_unittest.cc", + "bookmark_model_type_processor_unittest.cc", ] deps = [
diff --git a/components/sync_bookmarks/bookmark_data_type_controller.h b/components/sync_bookmarks/bookmark_data_type_controller.h index 62c27415..781333d 100644 --- a/components/sync_bookmarks/bookmark_data_type_controller.h +++ b/components/sync_bookmarks/bookmark_data_type_controller.h
@@ -7,7 +7,6 @@ #include <string> -#include "base/compiler_specific.h" #include "base/macros.h" #include "base/scoped_observer.h" #include "components/bookmarks/browser/base_bookmark_model_observer.h"
diff --git a/components/sync_bookmarks/bookmark_model_type_controller.cc b/components/sync_bookmarks/bookmark_model_type_controller.cc new file mode 100644 index 0000000..832fe9a --- /dev/null +++ b/components/sync_bookmarks/bookmark_model_type_controller.cc
@@ -0,0 +1,71 @@ +// Copyright 2017 The Chromium Authors. 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/sync_bookmarks/bookmark_model_type_controller.h" + +namespace sync_bookmarks { + +BookmarkModelTypeController::BookmarkModelTypeController() + : DataTypeController(syncer::BOOKMARKS) {} + +bool BookmarkModelTypeController::ShouldLoadModelBeforeConfigure() const { + NOTIMPLEMENTED(); + return false; +} + +void BookmarkModelTypeController::BeforeLoadModels( + syncer::ModelTypeConfigurer* configurer) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::LoadModels( + const ModelLoadCallback& model_load_callback) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::RegisterWithBackend( + base::Callback<void(bool)> set_downloaded, + syncer::ModelTypeConfigurer* configurer) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::StartAssociating( + const StartCallback& start_callback) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::ActivateDataType( + syncer::ModelTypeConfigurer* configurer) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::DeactivateDataType( + syncer::ModelTypeConfigurer* configurer) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::Stop() { + NOTIMPLEMENTED(); +} + +syncer::DataTypeController::State BookmarkModelTypeController::state() const { + NOTIMPLEMENTED(); + return NOT_RUNNING; +} + +void BookmarkModelTypeController::GetAllNodes( + const AllNodesCallback& callback) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::GetStatusCounters( + const StatusCountersCallback& callback) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeController::RecordMemoryUsageHistogram() { + NOTIMPLEMENTED(); +} + +} // namespace sync_bookmarks
diff --git a/components/sync_bookmarks/bookmark_model_type_controller.h b/components/sync_bookmarks/bookmark_model_type_controller.h new file mode 100644 index 0000000..49f69745 --- /dev/null +++ b/components/sync_bookmarks/bookmark_model_type_controller.h
@@ -0,0 +1,40 @@ +// Copyright 2017 The Chromium Authors. 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_SYNC_BOOKMARKS_BOOKMARK_MODEL_TYPE_CONTROLLER_H_ +#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_TYPE_CONTROLLER_H_ + +#include "base/macros.h" +#include "components/sync/driver/data_type_controller.h" + +namespace sync_bookmarks { + +// A class that manages the startup and shutdown of bookmark sync implemented +// through USS APIs. +class BookmarkModelTypeController : public syncer::DataTypeController { + public: + BookmarkModelTypeController(); + + // syncer::DataTypeController implementation. + bool ShouldLoadModelBeforeConfigure() const override; + void BeforeLoadModels(syncer::ModelTypeConfigurer* configurer) override; + void LoadModels(const ModelLoadCallback& model_load_callback) override; + void RegisterWithBackend(base::Callback<void(bool)> set_downloaded, + syncer::ModelTypeConfigurer* configurer) override; + void StartAssociating(const StartCallback& start_callback) override; + void ActivateDataType(syncer::ModelTypeConfigurer* configurer) override; + void DeactivateDataType(syncer::ModelTypeConfigurer* configurer) override; + void Stop() override; + State state() const override; + void GetAllNodes(const AllNodesCallback& callback) override; + void GetStatusCounters(const StatusCountersCallback& callback) override; + void RecordMemoryUsageHistogram() override; + + private: + DISALLOW_COPY_AND_ASSIGN(BookmarkModelTypeController); +}; + +} // namespace sync_bookmarks + +#endif // COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_TYPE_CONTROLLER_H_
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc new file mode 100644 index 0000000..db7ecbe --- /dev/null +++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. 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/sync_bookmarks/bookmark_model_type_processor.h" + +#include "components/sync/base/model_type.h" +#include "components/sync/engine/commit_queue.h" + +namespace sync_bookmarks { + +BookmarkModelTypeProcessor::BookmarkModelTypeProcessor() = default; + +BookmarkModelTypeProcessor::~BookmarkModelTypeProcessor() = default; + +void BookmarkModelTypeProcessor::ConnectSync( + std::unique_ptr<syncer::CommitQueue> worker) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeProcessor::DisconnectSync() { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeProcessor::GetLocalChanges( + size_t max_entries, + const GetLocalChangesCallback& callback) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeProcessor::OnCommitCompleted( + const sync_pb::ModelTypeState& type_state, + const syncer::CommitResponseDataList& response_list) { + NOTIMPLEMENTED(); +} + +void BookmarkModelTypeProcessor::OnUpdateReceived( + const sync_pb::ModelTypeState& model_type_state, + const syncer::UpdateResponseDataList& updates) { + NOTIMPLEMENTED(); +} + +} // namespace sync_bookmarks
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.h b/components/sync_bookmarks/bookmark_model_type_processor.h new file mode 100644 index 0000000..5ced433 --- /dev/null +++ b/components/sync_bookmarks/bookmark_model_type_processor.h
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. 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_SYNC_BOOKMARKS_BOOKMARK_MODEL_TYPE_PROCESSOR_H_ +#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_TYPE_PROCESSOR_H_ + +#include <memory> + +#include "base/macros.h" +#include "components/sync/engine/model_type_processor.h" + +namespace sync_bookmarks { + +class BookmarkModelTypeProcessor : public syncer::ModelTypeProcessor { + public: + BookmarkModelTypeProcessor(); + ~BookmarkModelTypeProcessor() override; + + // ModelTypeProcessor implementation. + void ConnectSync(std::unique_ptr<syncer::CommitQueue> worker) override; + void DisconnectSync() override; + void GetLocalChanges(size_t max_entries, + const GetLocalChangesCallback& callback) override; + void OnCommitCompleted( + const sync_pb::ModelTypeState& type_state, + const syncer::CommitResponseDataList& response_list) override; + void OnUpdateReceived(const sync_pb::ModelTypeState& type_state, + const syncer::UpdateResponseDataList& updates) override; + + private: + DISALLOW_COPY_AND_ASSIGN(BookmarkModelTypeProcessor); +}; + +} // namespace sync_bookmarks + +#endif // COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_TYPE_PROCESSOR_H_
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc new file mode 100644 index 0000000..b3d40e3 --- /dev/null +++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -0,0 +1,21 @@ +// Copyright 2017 The Chromium Authors. 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/sync_bookmarks/bookmark_model_type_processor.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace sync_bookmarks { + +namespace { + +class BookmarkModelTypeProcessorTest : public testing::Test {}; + +TEST_F(BookmarkModelTypeProcessorTest, CreateInstance) { + BookmarkModelTypeProcessor processor; +} + +} // namespace + +} // namespace sync_bookmarks
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc index 9bc296fc..af4eae1f 100644 --- a/components/variations/service/variations_field_trial_creator.cc +++ b/components/variations/service/variations_field_trial_creator.cc
@@ -126,7 +126,9 @@ : client_(client), ui_string_overrider_(ui_string_overrider), seed_store_(local_state), - create_trials_from_seed_called_(false) {} + create_trials_from_seed_called_(false), + has_platform_override_(false), + platform_override_(Study::PLATFORM_WINDOWS) {} VariationsFieldTrialCreator::~VariationsFieldTrialCreator() {} @@ -218,7 +220,9 @@ state->version = version; state->channel = GetChannelForVariations(client_->GetChannel()); state->form_factor = GetCurrentFormFactor(); - state->platform = ClientFilterableState::GetCurrentPlatform(); + state->platform = (has_platform_override_) + ? platform_override_ + : ClientFilterableState::GetCurrentPlatform(); state->hardware_class = GetHardwareClass(); #if defined(OS_ANDROID) // This is set on Android only currently, because the IsLowEndDevice() API @@ -329,6 +333,12 @@ return seed_store_.LoadSeed(seed); } +void VariationsFieldTrialCreator::OverrideVariationsPlatform( + Study::Platform platform_override) { + has_platform_override_ = true; + platform_override_ = platform_override; +} + bool VariationsFieldTrialCreator::SetupFieldTrials( const char* kEnableGpuBenchmarking, const char* kEnableFeatures,
diff --git a/components/variations/service/variations_field_trial_creator.h b/components/variations/service/variations_field_trial_creator.h index a8ef3f9..548267355 100644 --- a/components/variations/service/variations_field_trial_creator.h +++ b/components/variations/service/variations_field_trial_creator.h
@@ -101,6 +101,10 @@ // so that it can be overridden by tests. virtual bool LoadSeed(VariationsSeed* seed); + // Allow the platform that is used to filter the set of active trials + // to be overridden. + void OverrideVariationsPlatform(Study::Platform platform_override); + private: PrefService* local_state() { return seed_store_.local_state(); } @@ -133,6 +137,14 @@ // it gets called prior to |StartRepeatedVariationsSeedFetch|. bool create_trials_from_seed_called_; + // Indiciate if OverrideVariationsPlatform has been used to set + // |platform_override_|. + bool has_platform_override_; + + // Platform to be used for variations filtering, overridding the current + // platform. + Study::Platform platform_override_; + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(VariationsFieldTrialCreator);
diff --git a/content/browser/renderer_host/input/legacy_input_router_impl.cc b/content/browser/renderer_host/input/legacy_input_router_impl.cc index b214d96..253f419 100644 --- a/content/browser/renderer_host/input/legacy_input_router_impl.cc +++ b/content/browser/renderer_host/input/legacy_input_router_impl.cc
@@ -420,12 +420,6 @@ const WebInputEvent& input_event, const ui::LatencyInfo& latency_info, InputEventDispatchType dispatch_type) { - DCHECK(input_event.GetType() != blink::WebInputEvent::kGestureFlingStart || - static_cast<const blink::WebGestureEvent&>(input_event) - .data.fling_start.velocity_x != 0.0 || - static_cast<const blink::WebGestureEvent&>(input_event) - .data.fling_start.velocity_y != 0.0); - // This conversion is temporary. WebInputEvent should be generated // directly from ui::Event with the viewport coordinates. See // crbug.com/563730.
diff --git a/content/public/android/java/src/org/chromium/content/browser/SmartSelectionClient.java b/content/public/android/java/src/org/chromium/content/browser/SmartSelectionClient.java index ac1a2af..1990bca 100644 --- a/content/public/android/java/src/org/chromium/content/browser/SmartSelectionClient.java +++ b/content/public/android/java/src/org/chromium/content/browser/SmartSelectionClient.java
@@ -130,7 +130,7 @@ @CalledByNative private void onSurroundingTextReceived( @RequestType int callbackData, String text, int start, int end) { - if (TextUtils.isEmpty(text)) { + if (!textHasValidSelection(text, start, end)) { mCallback.onClassified(new SmartSelectionProvider.Result()); return; } @@ -150,6 +150,10 @@ } } + private boolean textHasValidSelection(String text, int start, int end) { + return !TextUtils.isEmpty(text) && 0 <= start && start < end && end <= text.length(); + } + private native long nativeInit(WebContents webContents); private native void nativeRequestSurroundingText( long nativeSmartSelectionClient, int numExtraCharacters, int callbackData);
diff --git a/content/public/renderer/render_thread.h b/content/public/renderer/render_thread.h index 6a02634..dcda3b1 100644 --- a/content/public/renderer/render_thread.h +++ b/content/public/renderer/render_thread.h
@@ -22,6 +22,12 @@ class WaitableEvent; } +namespace blink { +namespace scheduler { +enum class RendererProcessType; +} +} // namespace blink + namespace IPC { class MessageFilter; class SyncChannel; @@ -111,6 +117,10 @@ virtual scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() = 0; virtual scoped_refptr<base::SingleThreadTaskRunner> GetLoadingTaskRunner() = 0; + + // Set the renderer process type. + virtual void SetRendererProcessType( + blink::scheduler::RendererProcessType type) = 0; }; } // namespace content
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc index 2bc7194..3da45ce 100644 --- a/content/public/test/mock_render_thread.cc +++ b/content/public/test/mock_render_thread.cc
@@ -235,6 +235,9 @@ return base::ThreadTaskRunnerHandle::Get(); } +void MockRenderThread::SetRendererProcessType( + blink::scheduler::RendererProcessType type) {} + #if defined(OS_WIN) void MockRenderThread::PreCacheFont(const LOGFONT& log_font) { }
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h index 076e6fe..5350017 100644 --- a/content/public/test/mock_render_thread.h +++ b/content/public/test/mock_render_thread.h
@@ -84,6 +84,8 @@ int32_t GetClientId() override; scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> GetLoadingTaskRunner() override; + void SetRendererProcessType( + blink::scheduler::RendererProcessType type) override; #if defined(OS_WIN) void PreCacheFont(const LOGFONT& log_font) override; void ReleaseCachedFonts() override;
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 4055636..3b28891 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -745,8 +745,9 @@ } void RenderWidgetCompositor::SetViewportSize( - const gfx::Size& device_viewport_size) { - layer_tree_host_->SetViewportSize(device_viewport_size); + const gfx::Size& device_viewport_size, + const viz::LocalSurfaceId& local_surface_id) { + layer_tree_host_->SetViewportSize(device_viewport_size, local_surface_id); } viz::FrameSinkId RenderWidgetCompositor::GetFrameSinkId() { @@ -1286,11 +1287,6 @@ layer_tree_host_->SetContentSourceId(id); } -void RenderWidgetCompositor::SetLocalSurfaceId( - const viz::LocalSurfaceId& local_surface_id) { - layer_tree_host_->SetLocalSurfaceId(local_surface_id); -} - void RenderWidgetCompositor::NotifySwapTime(ReportTimeCallback callback) { QueueSwapPromise(base::MakeUnique<ReportTimeSwapPromise>( std::move(callback), base::ThreadTaskRunnerHandle::Get()));
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h index cfaa25e..cdcd003 100644 --- a/content/renderer/gpu/render_widget_compositor.h +++ b/content/renderer/gpu/render_widget_compositor.h
@@ -118,8 +118,8 @@ void SetRasterColorSpace(const gfx::ColorSpace& color_space); void SetIsForOopif(bool is_for_oopif); void SetContentSourceId(uint32_t source_id); - void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id); - void SetViewportSize(const gfx::Size& device_viewport_size); + void SetViewportSize(const gfx::Size& device_viewport_size, + const viz::LocalSurfaceId& local_surface_id); // WebLayerTreeView implementation. viz::FrameSinkId GetFrameSinkId() override;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 0c23197..c20fac2c 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1550,6 +1550,11 @@ return renderer_scheduler_->LoadingTaskRunner(); } +void RenderThreadImpl::SetRendererProcessType( + blink::scheduler::RendererProcessType type) { + renderer_scheduler_->SetRendererProcessType(type); +} + void RenderThreadImpl::OnAssociatedInterfaceRequest( const std::string& name, mojo::ScopedInterfaceEndpointHandle handle) {
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 2649e89c..30489e0 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -227,6 +227,8 @@ int32_t GetClientId() override; scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> GetLoadingTaskRunner() override; + void SetRendererProcessType( + blink::scheduler::RendererProcessType type) override; // IPC::Listener implementation via ChildThreadImpl: void OnAssociatedInterfaceRequest(
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index f5a8d1b..8b007888 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1256,18 +1256,18 @@ local_surface_id_ = *params.local_surface_id; if (compositor_) { - compositor_->SetViewportSize(params.physical_backing_size); - compositor_->SetBrowserControlsHeight( - params.top_controls_height, params.bottom_controls_height, - params.browser_controls_shrink_blink_size); - compositor_->SetRasterColorSpace( - screen_info_.color_space.GetRasterColorSpace()); // If surface synchronization is enable, then this will use the provided // |local_surface_id_| to submit the next generated CompositorFrame. // If the ID is not valid, then the compositor will defer commits until // it receives a valid surface ID. This is a no-op if surface // synchronization is disabled. - compositor_->SetLocalSurfaceId(local_surface_id_); + compositor_->SetViewportSize(params.physical_backing_size, + local_surface_id_); + compositor_->SetBrowserControlsHeight( + params.top_controls_height, params.bottom_controls_height, + params.browser_controls_shrink_blink_size); + compositor_->SetRasterColorSpace( + screen_info_.color_space.GetRasterColorSpace()); } visible_viewport_size_ = params.visible_viewport_size; @@ -1338,8 +1338,11 @@ void RenderWidget::AutoResizeCompositor() { physical_backing_size_ = gfx::ScaleToCeiledSize(size_, device_scale_factor_); + // A new LocalSurfaceId will need to be allocated by the browser for the new + // size. + local_surface_id_ = viz::LocalSurfaceId(); if (compositor_) - compositor_->SetViewportSize(physical_backing_size_); + compositor_->SetViewportSize(physical_backing_size_, local_surface_id_); } blink::WebLayerTreeView* RenderWidget::InitializeLayerTreeView() { @@ -1356,12 +1359,11 @@ compositor_->Initialize(std::move(layer_tree_host), std::move(animation_host)); - compositor_->SetViewportSize(physical_backing_size_); + compositor_->SetViewportSize(physical_backing_size_, local_surface_id_); OnDeviceScaleFactorChanged(); compositor_->SetRasterColorSpace( screen_info_.color_space.GetRasterColorSpace()); compositor_->SetContentSourceId(current_content_source_id_); - compositor_->SetLocalSurfaceId(local_surface_id_); // For background pages and certain tests, we don't want to trigger // LayerTreeFrameSink creation. bool should_generate_frame_sink =
diff --git a/content/shell/test_runner/mock_web_theme_engine.cc b/content/shell/test_runner/mock_web_theme_engine.cc index 59009cc..93a4c1a 100644 --- a/content/shell/test_runner/mock_web_theme_engine.cc +++ b/content/shell/test_runner/mock_web_theme_engine.cc
@@ -210,11 +210,15 @@ flags.setColor(color); flags.setStyle(cc::PaintFlags::kFill_Style); - canvas->drawCircle(cx, cy, radius, flags); + canvas->drawOval( + SkRect::MakeLTRB(cx - radius, cy - radius, cx + radius, cy + radius), + flags); flags.setColor(edgeColor); flags.setStyle(cc::PaintFlags::kStroke_Style); - canvas->drawCircle(cx, cy, radius, flags); + canvas->drawOval( + SkRect::MakeLTRB(cx - radius, cy - radius, cx + radius, cy + radius), + flags); } void nestedBoxes(cc::PaintCanvas* canvas,
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index cb63e501..073efff20 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc
@@ -16,6 +16,8 @@ #include "base/time/time.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/devtools_agent_host.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -442,8 +444,30 @@ const content::WebContents* web_contents) { if (!web_contents->GetSiteInstance()) return nullptr; - return extension_registry_->enabled_extensions().GetByID( - GetExtensionIdForSiteInstance(web_contents->GetSiteInstance())); + const Extension* extension = + extension_registry_->enabled_extensions().GetByID( + GetExtensionIdForSiteInstance(web_contents->GetSiteInstance())); + if (extension && extension->is_hosted_app()) { + // For hosted apps, be sure to exclude URLs outside of the app that might + // be loaded in the same SiteInstance (extensions guarantee that only + // extension urls are loaded in that SiteInstance). + const content::NavigationController& controller = + web_contents->GetController(); + content::NavigationEntry* entry = controller.GetLastCommittedEntry(); + // If there is no last committed entry, check the pending entry. This can + // happen in cases where we query this before any entry is fully committed, + // such as when attributing a WebContents for the TaskManager. If there is + // a committed navigation, use that instead. + if (!entry) + entry = controller.GetPendingEntry(); + if (!entry || + extension_registry_->enabled_extensions().GetExtensionOrAppByURL( + entry->GetURL()) != extension) { + return nullptr; + } + } + + return extension; } int ProcessManager::GetLazyKeepaliveCount(const Extension* extension) {
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h index e4843160..2afd31f1 100644 --- a/extensions/browser/process_manager.h +++ b/extensions/browser/process_manager.h
@@ -108,10 +108,13 @@ // already been sent the unload event and is shutting down. bool IsBackgroundHostClosing(const std::string& extension_id); - // Returns the extension associated with the specified RenderFrameHost/ - // WebContents, or null. + // Returns the extension associated with the specified RenderFrameHost, + // or null. const Extension* GetExtensionForRenderFrameHost( content::RenderFrameHost* render_frame_host); + + // Returns the extension associated with the main frame of the given + // |web_contents|, or null if there isn't one. const Extension* GetExtensionForWebContents( const content::WebContents* web_contents);
diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc index f49e9292..7bcc6d3 100644 --- a/extensions/browser/sandboxed_unpacker.cc +++ b/extensions/browser/sandboxed_unpacker.cc
@@ -577,8 +577,6 @@ return ASCIIToUTF16("ERROR_RE_ENCODING_THEME_IMAGE"); case ERROR_SAVING_THEME_IMAGE: return ASCIIToUTF16("ERROR_SAVING_THEME_IMAGE"); - case ABORTED_DUE_TO_SHUTDOWN: - return ASCIIToUTF16("ABORTED_DUE_TO_SHUTDOWN"); case COULD_NOT_READ_CATALOG_DATA_FROM_DISK: return ASCIIToUTF16("COULD_NOT_READ_CATALOG_DATA_FROM_DISK"); @@ -599,6 +597,7 @@ case DIRECTORY_MOVE_FAILED: return ASCIIToUTF16("DIRECTORY_MOVE_FAILED"); + case DEPRECATED_ABORTED_DUE_TO_SHUTDOWN: case NUM_FAILURE_REASONS: NOTREACHED(); return base::string16(); @@ -796,15 +795,6 @@ // Write our parsed images back to disk as well. for (size_t i = 0; i < images.size(); ++i) { - if (BrowserThread::GetBlockingPool()->IsShutdownInProgress()) { - // Abort package installation if shutdown was initiated, crbug.com/235525 - ReportFailure( - ABORTED_DUE_TO_SHUTDOWN, - l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_INSTALL_ERROR, - ASCIIToUTF16("ABORTED_DUE_TO_SHUTDOWN"))); - return false; - } - const SkBitmap& image = std::get<0>(images[i]); base::FilePath path_suffix = std::get<1>(images[i]); if (path_suffix.MaybeAsASCII() == install_icon_path)
diff --git a/extensions/browser/sandboxed_unpacker.h b/extensions/browser/sandboxed_unpacker.h index c8bb78b..10ed871c 100644 --- a/extensions/browser/sandboxed_unpacker.h +++ b/extensions/browser/sandboxed_unpacker.h
@@ -94,6 +94,14 @@ // passing the |location| and |creation_flags| to Extension::Create. The // |extensions_dir| parameter should specify the directory under which we'll // create a subdirectory to write the unpacked extension contents. + // Note: Because this requires disk I/O, the task runner passed should use + // TaskShutdownBehavior::SKIP_ON_SHUTDOWN to ensure that either the task is + // fully run (if initiated before shutdown) or not run at all (if shutdown is + // initiated first). See crbug.com/235525. + // TODO(devlin): We should probably just have SandboxedUnpacker use the common + // ExtensionFileTaskRunner, and not pass in a separate one. + // TODO(devlin): SKIP_ON_SHUTDOWN is also not quite sufficient for this. We + // should probably instead be using base::ImportantFileWriter or similar. SandboxedUnpacker( Manifest::Location location, int creation_flags, @@ -160,7 +168,7 @@ INVALID_PATH_FOR_BITMAP_IMAGE, ERROR_RE_ENCODING_THEME_IMAGE, ERROR_SAVING_THEME_IMAGE, - ABORTED_DUE_TO_SHUTDOWN, + DEPRECATED_ABORTED_DUE_TO_SHUTDOWN, // No longer used; kept for UMA. // SandboxedUnpacker::RewriteCatalogFiles() COULD_NOT_READ_CATALOG_DATA_FROM_DISK,
diff --git a/gpu/ipc/service/stream_texture_android.cc b/gpu/ipc/service/stream_texture_android.cc index dea1f36a..3003f14 100644 --- a/gpu/ipc/service/stream_texture_android.cc +++ b/gpu/ipc/service/stream_texture_android.cc
@@ -145,7 +145,7 @@ return false; if (!owner_stub_ || !surface_texture_.get()) - return true; + return false; GLint texture_id; glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id);
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm index 989be9a..a4553c4e 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -12,6 +12,9 @@ #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/metrics/tab_usage_recorder.h" #import "ios/chrome/browser/metrics/tab_usage_recorder_test_util.h" +#import "ios/chrome/browser/ui/settings/privacy_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" +#import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" #include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" @@ -109,7 +112,9 @@ // synchronization. void OpenNewMainTabUsingUIUnsynced() { int nb_main_tab = chrome_test_util::GetMainTabCount(); - WaitAndTap(chrome_test_util::ToolsMenuButton(), @"Tool menu"); + id<GREYMatcher> tool_menu_matcher = + grey_accessibilityID(kToolbarToolsMenuButtonIdentifier); + WaitAndTap(tool_menu_matcher, @"Tool menu"); id<GREYMatcher> new_main_tab_button_matcher = grey_accessibilityID(kToolsMenuNewTabId); WaitAndTap(new_main_tab_button_matcher, @"New tab button"); @@ -522,7 +527,9 @@ [[GREYConfiguration sharedInstance] setValue:@(NO) forConfigKey:kGREYConfigKeySynchronizationEnabled]; - Wait(chrome_test_util::ToolsMenuButton(), @"Tool Menu"); + id<GREYMatcher> toolMenuMatcher = + grey_accessibilityID(kToolbarToolsMenuButtonIdentifier); + Wait(toolMenuMatcher, @"Tool Menu"); GREYAssertTrue(chrome_test_util::SimulateTabsBackgrounding(), @"Failed to simulate tab backgrounding.");
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index b17ee78a3fa..a841f75d 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -266,6 +266,7 @@ "//ios/chrome/browser/ui/find_bar", "//ios/chrome/browser/ui/first_run", "//ios/chrome/browser/ui/history", + "//ios/chrome/browser/ui/history_popup/requirements", "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/ntp", "//ios/chrome/browser/ui/ntp/recent_tabs", @@ -390,6 +391,8 @@ "//ios/chrome/browser/ui/elements:elements_internal", "//ios/chrome/browser/ui/find_bar", "//ios/chrome/browser/ui/first_run", + "//ios/chrome/browser/ui/history_popup:coordinator", + "//ios/chrome/browser/ui/history_popup/requirements", "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/ntp", "//ios/chrome/browser/ui/ntp:ntp_controller",
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 2338cae..1a17eb0 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -121,6 +121,8 @@ #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h" #import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h" #import "ios/chrome/browser/ui/fullscreen_controller.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h" +#import "ios/chrome/browser/ui/history_popup/tab_history_coordinator.h" #import "ios/chrome/browser/ui/key_commands_provider.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_controller.h" #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_view_controller.h" @@ -361,6 +363,7 @@ StoreKitLauncher, TabDialogDelegate, TabHeadersDelegate, + TabHistoryPresentation, TabModelObserver, TabSnapshottingDelegate, UIGestureRecognizerDelegate, @@ -524,6 +527,9 @@ // Coordinator for displaying alerts. AlertCoordinator* _alertCoordinator; + + // Coordinator for Tab History Popup. + TabHistoryCoordinator* _tabHistoryCoordinator; } // The browser's side swipe controller. Lazily instantiated on the first call. @@ -1742,6 +1748,10 @@ [_model browserStateDestroyed]; [_preloadController browserStateDestroyed]; _preloadController = nil; + + // Disconnect child coordinators. + [_tabHistoryCoordinator disconnect]; + // The file remover needs the browser state, so needs to be destroyed now. _externalFileRemover = nil; _browserState = nullptr; @@ -1830,6 +1840,15 @@ [[_model currentTab] infoBarManager]; _infoBarContainer->ChangeInfoBarManager(infoBarManager); + // Create child coordinators. + _tabHistoryCoordinator = + [[TabHistoryCoordinator alloc] initWithBaseViewController:self]; + _tabHistoryCoordinator.dispatcher = _dispatcher; + _tabHistoryCoordinator.positionProvider = _toolbarController; + _tabHistoryCoordinator.tabModel = _model; + _tabHistoryCoordinator.presentationProvider = self; + _tabHistoryCoordinator.tabHistoryUIUpdater = _toolbarController; + if (base::FeatureList::IsEnabled(payments::features::kWebPayments)) { _paymentRequestManager = [[PaymentRequestManager alloc] initWithBaseViewController:self @@ -1994,7 +2013,6 @@ - (void)dismissPopups { [_toolbarController dismissToolsMenuPopup]; [self hidePageInfoPopupForView:nil]; - [_toolbarController dismissTabHistoryPopup]; [self.bubbleViewControllerPresenter dismissAnimated:YES]; } @@ -4140,42 +4158,6 @@ completion:nil]; } -- (void)showTabHistoryPopupForBackwardHistory { - DCHECK(self.visible || self.dismissingModal); - - // Dismiss the omnibox (if open). - [_toolbarController cancelOmniboxEdit]; - // Dismiss the soft keyboard (if open). - Tab* tab = [_model currentTab]; - [tab.webController dismissKeyboard]; - web::NavigationItemList backwardItems = - [tab navigationManager]->GetBackwardItems(); - [_toolbarController showTabHistoryPopupInView:[self view] - withItems:backwardItems - forBackHistory:YES]; -} - -- (void)showTabHistoryPopupForForwardHistory { - DCHECK(self.visible || self.dismissingModal); - - // Dismiss the omnibox (if open). - [_toolbarController cancelOmniboxEdit]; - // Dismiss the soft keyboard (if open). - Tab* tab = [_model currentTab]; - [tab.webController dismissKeyboard]; - - web::NavigationItemList forwardItems = - [tab navigationManager]->GetForwardItems(); - [_toolbarController showTabHistoryPopupInView:[self view] - withItems:forwardItems - forBackHistory:NO]; -} - -- (void)navigateToHistoryItem:(const web::NavigationItem*)item { - [[_model currentTab] goToItem:item]; - [_toolbarController dismissTabHistoryPopup]; -} - - (void)showReadingList { _readingListCoordinator = [[ReadingListCoordinator alloc] initWithBaseViewController:self @@ -5123,4 +5105,12 @@ return [self currentLogoAnimationControllerOwner]; } +#pragma mark - TabHistoryPresenter + +- (void)prepareForTabHistoryPresentation { + DCHECK(self.visible || self.dismissingModal); + [[self.tabModel currentTab].webController dismissKeyboard]; + [_toolbarController cancelOmniboxEdit]; +} + @end
diff --git a/ios/chrome/browser/ui/commands/BUILD.gn b/ios/chrome/browser/ui/commands/BUILD.gn index fb70574..6807233 100644 --- a/ios/chrome/browser/ui/commands/BUILD.gn +++ b/ios/chrome/browser/ui/commands/BUILD.gn
@@ -13,6 +13,7 @@ "clear_browsing_data_command.mm", "generic_chrome_command.h", "generic_chrome_command.mm", + "history_popup_commands.h", "ios_command_ids.h", "open_new_tab_command.h", "open_new_tab_command.mm",
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index e0b50d64..de94444 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -7,15 +7,14 @@ #import <Foundation/Foundation.h> +#import "ios/chrome/browser/ui/commands/history_popup_commands.h" + @class OpenNewTabCommand; @class ReadingListAddCommand; -namespace web { -class NavigationItem; -} // Protocol for commands that will generally be handled by the "current tab", // which in practice is the BrowserViewController instance displaying the tab. -@protocol BrowserCommands<NSObject> +@protocol BrowserCommands<NSObject, TabHistoryPopupCommands> // Closes the current tab. - (void)closeCurrentTab; @@ -53,15 +52,6 @@ // Shows the QR scanner UI. - (void)showQRScanner; -// Shows the tab history popup containing the tab's backward history. -- (void)showTabHistoryPopupForBackwardHistory; - -// Shows the tab history popup containing the tab's forward history. -- (void)showTabHistoryPopupForForwardHistory; - -// Navigate back/forward to the selected entry in the tab's history. -- (void)navigateToHistoryItem:(const web::NavigationItem*)item; - // Shows the Reading List UI. - (void)showReadingList;
diff --git a/ios/chrome/browser/ui/commands/history_popup_commands.h b/ios/chrome/browser/ui/commands/history_popup_commands.h new file mode 100644 index 0000000..7d8e820 --- /dev/null +++ b/ios/chrome/browser/ui/commands/history_popup_commands.h
@@ -0,0 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_COMMANDS_HISTORY_POPUP_COMMANDS_H_ +#define IOS_CHROME_BROWSER_UI_COMMANDS_HISTORY_POPUP_COMMANDS_H_ + +#import <Foundation/Foundation.h> + +namespace web { +class NavigationItem; +} + +@protocol TabHistoryPopupCommands +// Shows the tab history popup containing the tab's backward history. +- (void)showTabHistoryPopupForBackwardHistory; + +// Shows the tab history popup containing the tab's forward history. +- (void)showTabHistoryPopupForForwardHistory; + +// Navigate back/forward to the selected entry in the tab's history. +- (void)navigateToHistoryItem:(const web::NavigationItem*)item; +@end + +#endif // IOS_CHROME_BROWSER_UI_COMMANDS_HISTORY_POPUP_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen_controller.mm index e2eae0ce..aee4c268 100644 --- a/ios/chrome/browser/ui/fullscreen_controller.mm +++ b/ios/chrome/browser/ui/fullscreen_controller.mm
@@ -9,10 +9,10 @@ #include "base/logging.h" #import "ios/chrome/browser/ui/browser_view_controller.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h" #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h" #import "ios/chrome/browser/ui/tabs/tab_strip_controller.h" #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" -#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h" #import "ios/chrome/browser/ui/voice/voice_search_notification_names.h" #include "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h"
diff --git a/ios/chrome/browser/ui/history_popup/BUILD.gn b/ios/chrome/browser/ui/history_popup/BUILD.gn index 7bf1ad6..9b5f15e 100644 --- a/ios/chrome/browser/ui/history_popup/BUILD.gn +++ b/ios/chrome/browser/ui/history_popup/BUILD.gn
@@ -26,6 +26,23 @@ ] } +source_set("coordinator") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "tab_history_coordinator.h", + "tab_history_coordinator.mm", + ] + deps = [ + ":history_popup", + "//base", + "//ios/chrome/browser", + "//ios/chrome/browser/tabs", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/history_popup/requirements", + "//ios/shared/chrome/browser/ui/commands", + ] +} + source_set("unit_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true
diff --git a/ios/chrome/browser/ui/history_popup/requirements/BUILD.gn b/ios/chrome/browser/ui/history_popup/requirements/BUILD.gn new file mode 100644 index 0000000..f5dc3974 --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/requirements/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2017 The Chromium 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("requirements") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "tab_history_constants.h", + "tab_history_constants.mm", + "tab_history_positioner.h", + "tab_history_presentation.h", + "tab_history_ui_updater.h", + ] +}
diff --git a/ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h b/ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h new file mode 100644 index 0000000..fb8c5d7f --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_HISTORY_POPUP_CONSTANTS_H_ +#define IOS_CHROME_BROWSER_UI_HISTORY_POPUP_CONSTANTS_H_ + +#import <Foundation/Foundation.h> + +// Notification center names. +extern NSString* const kTabHistoryPopupWillShowNotification; +extern NSString* const kTabHistoryPopupWillHideNotification; + +// Toolbar buttons that can display the HistoryPopup. +typedef NS_OPTIONS(NSUInteger, ToolbarButton) { + // Back Toolbar Button. + ToolbarButtonForward = 0, + // Forward Toolbar Button. + ToolbarButtonBack = 1, +}; + +#endif // IOS_CHROME_BROWSER_UI_HISTORY_POPUP_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.mm b/ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.mm new file mode 100644 index 0000000..2b11d975 --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.mm
@@ -0,0 +1,10 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h" + +NSString* const kTabHistoryPopupWillShowNotification = + @"kTabHistoryPopupWillShowNotification"; +NSString* const kTabHistoryPopupWillHideNotification = + @"kTabHistoryPopupWillHideNotification";
diff --git a/ios/chrome/browser/ui/history_popup/requirements/tab_history_positioner.h b/ios/chrome/browser/ui/history_popup/requirements/tab_history_positioner.h new file mode 100644 index 0000000..5d7100b --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/requirements/tab_history_positioner.h
@@ -0,0 +1,15 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_POSITIONER_H_ +#define IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_POSITIONER_H_ + +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h" + +@protocol TabHistoryPositioner +// CGPoint which the Tab History Popup will be presented from. +- (CGPoint)originPointForToolbarButton:(ToolbarButton)toolbarButton; +@end + +#endif // IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_POSITIONER_H_
diff --git a/ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h b/ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h new file mode 100644 index 0000000..e565e171 --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h
@@ -0,0 +1,14 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_PRESENTATION_H_ +#define IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_PRESENTATION_H_ + +@protocol TabHistoryPresentation +@optional +// Tells the receiver the Tab History popup will be presented. +- (void)prepareForTabHistoryPresentation; +@end + +#endif // IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_PRESENTATION_H_
diff --git a/ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h b/ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h new file mode 100644 index 0000000..e73bbec --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h
@@ -0,0 +1,20 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_UI_UPDATER_H_ +#define IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_UI_UPDATER_H_ + +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h" + +@protocol TabHistoryUIUpdater +@optional +// Tells the receiver to update its UI now that TabHistory popup will be +// presented. +- (void)updateUIForTabHistoryPresentationFrom:(ToolbarButton)button; + +// Tells the receiver to update its UI now that TabHistory popup was dismissed. +- (void)updateUIForTabHistoryWasDismissed; +@end + +#endif // IOS_CHROME_BROWSER_UI_HISTORY_POPUP_REQUIREMENTS_TAB_HISTORY_UI_UPDATER_H_
diff --git a/ios/chrome/browser/ui/history_popup/tab_history_coordinator.h b/ios/chrome/browser/ui/history_popup/tab_history_coordinator.h new file mode 100644 index 0000000..6f9a1d47 --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/tab_history_coordinator.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_HISTORY_POPUP_TAB_HISTORY_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_HISTORY_POPUP_TAB_HISTORY_COORDINATOR_H_ + +#import "ios/chrome/browser/chrome_coordinator.h" + +@class CommandDispatcher; +@protocol PopupMenuDelegate; +@protocol TabHistoryPresentation; +@protocol TabHistoryPositioner; +@protocol TabHistoryUIUpdater; +@class TabModel; + +// The coordinator in charge of displaying and dismissing the TabHistoryPopup. +// The TabHistoryPopup is presented when the user long presses the back or +// forward Toolbar button. +@interface TabHistoryCoordinator : ChromeCoordinator + +// The dispatcher for this Coordinator. +@property(nonatomic, weak) CommandDispatcher* dispatcher; +// |positionProvider| provides the presentation origin for the TabHistoryPopup. +@property(nonatomic, weak) id<TabHistoryPositioner> positionProvider; +// |presentationProvider| runs tasks for before and after presenting the +// TabHistoryPopup. +@property(nonatomic, weak) id<TabHistoryPresentation> presentationProvider; +// |tabHistoryUIUpdater| updates the relevant UI before and after presenting +// the TabHistoryPopup. +@property(nonatomic, weak) id<TabHistoryUIUpdater> tabHistoryUIUpdater; +// The current TabModel being used by BVC. +@property(nonatomic, weak) TabModel* tabModel; +// Dissmisses the currently presented TabHistoryPopup, if none is being +// presented it will no-op. + +- (void)dismissHistoryPopup; +// Stops listening for dispatcher calls. +- (void)disconnect; + +@end + +#endif // IOS_CHROME_BROWSER_UI_HISTORY_POPUP_TAB_HISTORY_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/history_popup/tab_history_coordinator.mm b/ios/chrome/browser/ui/history_popup/tab_history_coordinator.mm new file mode 100644 index 0000000..d90504e --- /dev/null +++ b/ios/chrome/browser/ui/history_popup/tab_history_coordinator.mm
@@ -0,0 +1,175 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/history_popup/tab_history_coordinator.h" + +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#import "ios/chrome/browser/tabs/tab.h" +#import "ios/chrome/browser/tabs/tab_model.h" +#import "ios/chrome/browser/ui/commands/history_popup_commands.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_positioner.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h" +#import "ios/chrome/browser/ui/history_popup/tab_history_popup_controller.h" +#import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" +#include "ios/web/public/navigation_item.h" +#import "ios/web/public/navigation_manager.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using base::UserMetricsAction; + +@interface TabHistoryCoordinator ()<PopupMenuDelegate> + +// The TabHistoryPopupController instance that this coordinator will be +// presenting. +@property(nonatomic, strong) + TabHistoryPopupController* tabHistoryPopupController; + +@end + +@implementation TabHistoryCoordinator + +@synthesize dispatcher = _dispatcher; +@synthesize positionProvider = _positionProvider; +@synthesize presentationProvider = _presentationProvider; +@synthesize tabHistoryPopupController = _tabHistoryPopupController; +@synthesize tabHistoryUIUpdater = _tabHistoryUIUpdater; +@synthesize tabModel = _tabModel; + +- (void)disconnect { + self.dispatcher = nil; +} + +- (void)setDispatcher:(CommandDispatcher*)dispatcher { + if (dispatcher == self.dispatcher) { + return; + } + if (self.dispatcher) { + [self.dispatcher stopDispatchingToTarget:self]; + } + [dispatcher startDispatchingToTarget:self + forProtocol:@protocol(TabHistoryPopupCommands)]; + _dispatcher = dispatcher; +} + +#pragma mark - TabHistoryPopupCommands + +- (void)showTabHistoryPopupForBackwardHistory { + Tab* tab = [self.tabModel currentTab]; + web::NavigationItemList backwardItems = + [tab navigationManager]->GetBackwardItems(); + CGPoint origin = [self.baseViewController.view.window + convertPoint:[self.positionProvider + originPointForToolbarButton:ToolbarButtonBack] + toView:self.baseViewController.view]; + + [self.tabHistoryUIUpdater + updateUIForTabHistoryPresentationFrom:ToolbarButtonBack]; + [self presentTabHistoryPopupWithItems:backwardItems origin:origin]; +} + +- (void)showTabHistoryPopupForForwardHistory { + Tab* tab = [self.tabModel currentTab]; + web::NavigationItemList forwardItems = + [tab navigationManager]->GetForwardItems(); + CGPoint origin = [self.baseViewController.view.window + convertPoint:[self.positionProvider + originPointForToolbarButton:ToolbarButtonForward] + toView:self.baseViewController.view]; + + [self.tabHistoryUIUpdater + updateUIForTabHistoryPresentationFrom:ToolbarButtonForward]; + [self presentTabHistoryPopupWithItems:forwardItems origin:origin]; +} + +- (void)navigateToHistoryItem:(const web::NavigationItem*)item { + [[self.tabModel currentTab] goToItem:item]; + [self dismissPopupMenu:nil]; +} + +#pragma mark - Helper Methods + +// Present a Tab History Popup that displays |items|, and its view is presented +// from |origin|. +- (void)presentTabHistoryPopupWithItems:(const web::NavigationItemList&)items + origin:(CGPoint)historyPopupOrigin { + if (self.tabHistoryPopupController) + return; + base::RecordAction(UserMetricsAction("MobileToolbarShowTabHistoryMenu")); + + [self.presentationProvider prepareForTabHistoryPresentation]; + + // Initializing also displays the Tab History Popup VC. + self.tabHistoryPopupController = [[TabHistoryPopupController alloc] + initWithOrigin:historyPopupOrigin + parentView:self.baseViewController.view + items:items + dispatcher:static_cast<id<TabHistoryPopupCommands>>(self.dispatcher)]; + + [self.tabHistoryPopupController setDelegate:self]; + + // Notify observers that TabHistoryPopup will show. + [[NSNotificationCenter defaultCenter] + postNotificationName:kTabHistoryPopupWillShowNotification + object:nil]; + + // Register to receive notification for when the App is backgrounded so we can + // dismiss the TabHistoryPopup. + NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver:self + selector:@selector(applicationDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; +} + +// Dismiss the presented Tab History Popup. +- (void)dismissHistoryPopup { + if (!self.tabHistoryPopupController) + return; + __block TabHistoryPopupController* tempController = + self.tabHistoryPopupController; + [tempController containerView].userInteractionEnabled = NO; + [tempController dismissAnimatedWithCompletion:^{ + [self.tabHistoryUIUpdater updateUIForTabHistoryWasDismissed]; + // Reference tempTHPC so the block retains it. + tempController = nil; + }]; + // Reset _tabHistoryPopupController to prevent -applicationDidEnterBackground + // from posting another kTabHistoryPopupWillHideNotification. + self.tabHistoryPopupController = nil; + + // Stop listening for notifications since these are only used to dismiss the + // Tab History Popup. + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [[NSNotificationCenter defaultCenter] + postNotificationName:kTabHistoryPopupWillHideNotification + object:nil]; +} + +#pragma mark - PopupMenuDelegate + +- (void)dismissPopupMenu:(PopupMenuController*)controller { + [self dismissHistoryPopup]; +} + +#pragma mark - Observer Methods + +- (void)applicationDidEnterBackground:(NSNotification*)notify { + if (self.tabHistoryPopupController) { + // Dismiss the tab history popup without animation. + [self.tabHistoryUIUpdater updateUIForTabHistoryWasDismissed]; + self.tabHistoryPopupController = nil; + [[NSNotificationCenter defaultCenter] + postNotificationName:kTabHistoryPopupWillHideNotification + object:nil]; + } +} + +@end
diff --git a/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.h b/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.h index cc17f0c..73a6ee6 100644 --- a/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.h +++ b/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.h
@@ -9,7 +9,7 @@ #include "ios/web/public/navigation_item_list.h" -@protocol BrowserCommands; +@protocol TabHistoryPopupCommands; // The view controller for the tab history menu that appears when the user long // presses the back or forward button. @@ -17,11 +17,11 @@ // Initializes the popup to display |items| with the given |origin| that is // relevant to the |parent|'s coordinate system. -// |entries| is an array of CRWSessionEntries. - (id)initWithOrigin:(CGPoint)origin parentView:(UIView*)parent items:(const web::NavigationItemList&)items - dispatcher:(id<BrowserCommands>)dispatcher NS_DESIGNATED_INITIALIZER; + dispatcher:(id<TabHistoryPopupCommands>)dispatcher + NS_DESIGNATED_INITIALIZER; @end
diff --git a/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.mm b/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.mm index 2622557..c5be1138 100644 --- a/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.mm +++ b/ios/chrome/browser/ui/history_popup/tab_history_popup_controller.mm
@@ -65,7 +65,7 @@ - (id)initWithOrigin:(CGPoint)origin parentView:(UIView*)parent items:(const web::NavigationItemList&)items - dispatcher:(id<BrowserCommands>)dispatcher { + dispatcher:(id<TabHistoryPopupCommands>)dispatcher { DCHECK(parent); if ((self = [super initWithParentView:parent])) { // Create the table view controller. @@ -92,6 +92,12 @@ CGFloat popupWidth = [[self class] popupWidthForItems:items]; [self setOptimalSize:CGSizeMake(popupWidth, optimalHeight) atOrigin:newOrigin]; + + // Fade in the popup. + CGRect containerFrame = [[self popupContainer] frame]; + CGPoint destination = CGPointMake(CGRectGetLeadingEdge(containerFrame), + CGRectGetMinY(containerFrame)); + [self fadeInPopupFromSource:origin toDestination:destination]; } return self; }
diff --git a/ios/chrome/browser/ui/history_popup/tab_history_view_controller.h b/ios/chrome/browser/ui/history_popup/tab_history_view_controller.h index 5529d57..72664a8 100644 --- a/ios/chrome/browser/ui/history_popup/tab_history_view_controller.h +++ b/ios/chrome/browser/ui/history_popup/tab_history_view_controller.h
@@ -9,14 +9,14 @@ #include "ios/web/public/navigation_item_list.h" -@protocol BrowserCommands; +@protocol TabHistoryPopupCommands; // View controller for displaying a list of NavigationItems in a table. @interface TabHistoryViewController : UICollectionViewController // Designated initializer that takes a NavigationItemList. - (instancetype)initWithItems:(const web::NavigationItemList&)items - dispatcher:(id<BrowserCommands>)dispatcher + dispatcher:(id<TabHistoryPopupCommands>)dispatcher NS_DESIGNATED_INITIALIZER; // TabHistoryViewControllers must be initialized with |-initWithItems:|.
diff --git a/ios/chrome/browser/ui/history_popup/tab_history_view_controller.mm b/ios/chrome/browser/ui/history_popup/tab_history_view_controller.mm index 765e31d..e7f958c 100644 --- a/ios/chrome/browser/ui/history_popup/tab_history_view_controller.mm +++ b/ios/chrome/browser/ui/history_popup/tab_history_view_controller.mm
@@ -7,9 +7,7 @@ #include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" -#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" -#include "ios/chrome/browser/ui/commands/browser_commands.h" -#include "ios/chrome/browser/ui/commands/ios_command_ids.h" +#include "ios/chrome/browser/ui/commands/history_popup_commands.h" #import "ios/chrome/browser/ui/history_popup/tab_history_cell.h" #include "ios/chrome/browser/ui/rtl_geometry.h" #import "ios/third_party/material_components_ios/src/components/Ink/src/MaterialInk.h" @@ -266,7 +264,7 @@ - (void)clearNavigationItems; // The dispatcher used by this ViewController. -@property(nonatomic, readonly, weak) id<BrowserCommands> dispatcher; +@property(nonatomic, readonly, weak) id<TabHistoryPopupCommands> dispatcher; @end @@ -275,7 +273,7 @@ @synthesize dispatcher = _dispatcher; - (instancetype)initWithItems:(const web::NavigationItemList&)items - dispatcher:(id<BrowserCommands>)dispatcher { + dispatcher:(id<TabHistoryPopupCommands>)dispatcher { TabHistoryViewControllerLayout* layout = [[TabHistoryViewControllerLayout alloc] init]; if ((self = [super initWithCollectionViewLayout:layout])) {
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm index a706f20..5e9afa3 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm
@@ -283,10 +283,12 @@ EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (no hidden toolbar in tablet)"); } + NSString* toolsMenuLabel = l10n_util::GetNSString(IDS_IOS_TOOLBAR_SETTINGS); + // Check that the toolbar's tab switcher and tools menu buttons are visible. [[EarlGrey selectElementWithMatcher:chrome_test_util::ShowTabsButton()] assertWithMatcher:grey_sufficientlyVisible()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(toolsMenuLabel)] assertWithMatcher:grey_sufficientlyVisible()]; AssertNTPScrolledToTop(NO); @@ -299,7 +301,7 @@ // Check that tab switcher and tools menu buttons are not on screen. [[EarlGrey selectElementWithMatcher:chrome_test_util::ShowTabsButton()] assertWithMatcher:grey_notVisible()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuButton()] + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(toolsMenuLabel)] assertWithMatcher:grey_notVisible()]; }
diff --git a/ios/chrome/browser/ui/overscroll_actions/BUILD.gn b/ios/chrome/browser/ui/overscroll_actions/BUILD.gn index 13b54b5..bd98076a 100644 --- a/ios/chrome/browser/ui/overscroll_actions/BUILD.gn +++ b/ios/chrome/browser/ui/overscroll_actions/BUILD.gn
@@ -22,6 +22,7 @@ "//base", "//ios/chrome/app/theme", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui/history_popup/requirements", "//ios/chrome/browser/ui/static_content", "//ios/chrome/browser/ui/toolbar", "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm index c331fdf..6cefbc79 100644 --- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm +++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -10,11 +10,11 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #import "ios/chrome/browser/ui/browser_view_controller.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h" #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_gesture_recognizer.h" #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_view.h" #include "ios/chrome/browser/ui/rtl_geometry.h" #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" -#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h" #include "ios/chrome/browser/ui/uikit_ui_util.h" #import "ios/chrome/browser/ui/voice/voice_search_notification_names.h" #import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn index 011f19fe..74976925 100644 --- a/ios/chrome/browser/ui/toolbar/BUILD.gn +++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -65,7 +65,7 @@ "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/fancy_ui", "//ios/chrome/browser/ui/history", - "//ios/chrome/browser/ui/history_popup", + "//ios/chrome/browser/ui/history_popup/requirements", "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/popup_menu", "//ios/chrome/browser/ui/qr_scanner",
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h index a4e3039..36d2a142 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.h
@@ -7,6 +7,8 @@ #import <UIKit/UIKit.h> +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_positioner.h" +#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h" #include "ios/chrome/browser/ui/omnibox/omnibox_popup_positioner.h" #include "ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h" #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" @@ -84,6 +86,8 @@ @interface WebToolbarController : ToolbarController<OmniboxFocuser, QRScannerViewControllerDelegate, + TabHistoryPositioner, + TabHistoryUIUpdater, VoiceSearchControllerDelegate> @property(nonatomic, weak) id<WebToolbarDelegate> delegate; @@ -150,14 +154,6 @@ // if it is up to date. - (UIImage*)snapshotWithWidth:(CGFloat)width; -// Shows the tab history popup inside |view|. -- (void)showTabHistoryPopupInView:(UIView*)view - withItems:(const web::NavigationItemList&)items - forBackHistory:(BOOL)isBackHistory; - -// Dismisses the tab history popup. -- (void)dismissTabHistoryPopup; - // Returns whether omnibox is a first responder. - (BOOL)isOmniboxFirstResponder;
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm index d636742..a042e047 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -45,7 +45,6 @@ #import "ios/chrome/browser/ui/commands/generic_chrome_command.h" #include "ios/chrome/browser/ui/commands/ios_command_ids.h" #include "ios/chrome/browser/ui/commands/start_voice_search_command.h" -#import "ios/chrome/browser/ui/history_popup/tab_history_popup_controller.h" #import "ios/chrome/browser/ui/image_util.h" #include "ios/chrome/browser/ui/omnibox/location_bar_controller_impl.h" #include "ios/chrome/browser/ui/omnibox/omnibox_view_ios.h" @@ -87,10 +86,6 @@ using base::UserMetricsAction; using ios::material::TimingFunction; -NSString* const kTabHistoryPopupWillShowNotification = - @"kTabHistoryPopupWillShowNotification"; -NSString* const kTabHistoryPopupWillHideNotification = - @"kTabHistoryPopupWillHideNotification"; const CGFloat kiPhoneOmniboxPlaceholderColorBrightness = 150 / 255.0; // The histogram recording CLAuthorizationStatus for omnibox queries. @@ -285,10 +280,6 @@ // A hash of the state of the toolbar when the snapshot was taken. uint32_t _snapshotHash; - // View controller for displaying tab history when the user long presses the - // back or forward button. nil if not visible. - TabHistoryPopupController* _tabHistoryPopupController; - #if defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0) API_AVAILABLE(ios(11.0)) DropAndNavigateInteraction* _dropInteraction; #endif @@ -702,7 +693,6 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [_tabHistoryPopupController setDelegate:nil]; } #pragma mark - @@ -837,65 +827,6 @@ return _snapshot; } -- (void)showTabHistoryPopupInView:(UIView*)view - withItems:(const web::NavigationItemList&)items - forBackHistory:(BOOL)isBackHistory { - if (_tabHistoryPopupController) - return; - - base::RecordAction(UserMetricsAction("MobileToolbarShowTabHistoryMenu")); - - UIButton* historyButton = isBackHistory ? _backButton : _forwardButton; - // Keep the button pressed by swapping the normal and highlighted images. - [self setImagesForNavButton:historyButton withTabHistoryVisible:YES]; - - // Set the origin for the tools popup to the leading side of the bottom of the - // pressed buttons. - CGRect buttonBounds = [historyButton.imageView bounds]; - CGPoint origin = CGPointMake(CGRectGetLeadingEdge(buttonBounds), - CGRectGetMaxY(buttonBounds)); - CGPoint convertedOrigin = - [view convertPoint:origin fromView:historyButton.imageView]; - _tabHistoryPopupController = - [[TabHistoryPopupController alloc] initWithOrigin:convertedOrigin - parentView:view - items:items - dispatcher:self.dispatcher]; - [_tabHistoryPopupController setDelegate:self]; - - // Fade in the popup and notify observers. - CGRect containerFrame = [[_tabHistoryPopupController popupContainer] frame]; - CGPoint destination = CGPointMake(CGRectGetLeadingEdge(containerFrame), - CGRectGetMinY(containerFrame)); - [_tabHistoryPopupController fadeInPopupFromSource:convertedOrigin - toDestination:destination]; - [[NSNotificationCenter defaultCenter] - postNotificationName:kTabHistoryPopupWillShowNotification - object:nil]; -} - -- (void)dismissTabHistoryPopup { - if (!_tabHistoryPopupController) - return; - __block TabHistoryPopupController* tempTHPC = _tabHistoryPopupController; - [tempTHPC containerView].userInteractionEnabled = NO; - [tempTHPC dismissAnimatedWithCompletion:^{ - // Unpress the back/forward button by restoring the normal and - // highlighted images to their usual state. - [self setImagesForNavButton:_backButton withTabHistoryVisible:NO]; - [self setImagesForNavButton:_forwardButton withTabHistoryVisible:NO]; - // Reference tempTHPC so the block retains it. - tempTHPC = nil; - }]; - // reset _tabHistoryPopupController to prevent -applicationDidEnterBackground - // from posting another kTabHistoryPopupWillHideNotification. - _tabHistoryPopupController = nil; - - [[NSNotificationCenter defaultCenter] - postNotificationName:kTabHistoryPopupWillHideNotification - object:nil]; -} - - (BOOL)isOmniboxFirstResponder { return [_omniBox isFirstResponder]; } @@ -932,19 +863,6 @@ #pragma mark - #pragma mark Overridden superclass methods. -- (void)applicationDidEnterBackground:(NSNotification*)notify { - if (_tabHistoryPopupController) { - // Dismiss the tab history popup without animation. - [self setImagesForNavButton:_backButton withTabHistoryVisible:NO]; - [self setImagesForNavButton:_forwardButton withTabHistoryVisible:NO]; - _tabHistoryPopupController = nil; - [[NSNotificationCenter defaultCenter] - postNotificationName:kTabHistoryPopupWillHideNotification - object:nil]; - } - [super applicationDidEnterBackground:notify]; -} - - (void)setUpButton:(UIButton*)button withImageEnum:(int)imageEnum forInitialState:(UIControlState)initialState @@ -1426,17 +1344,6 @@ } #pragma mark - -#pragma mark PopupMenuDelegate methods. - -- (void)dismissPopupMenu:(PopupMenuController*)controller { - if ([controller isKindOfClass:[TabHistoryPopupController class]] && - (TabHistoryPopupController*)controller == _tabHistoryPopupController) - [self dismissTabHistoryPopup]; - else - [super dismissPopupMenu:controller]; -} - -#pragma mark - #pragma mark ToolbarFrameDelegate methods. - (void)frameDidChangeFrame:(CGRect)newFrame fromFrame:(CGRect)oldFrame { @@ -1508,6 +1415,32 @@ [_omniBox insertTextWhileEditing:text]; } +#pragma mark - TabHistory Requirements + +- (CGPoint)originPointForToolbarButton:(ToolbarButton)toolbarButton { + UIButton* historyButton = toolbarButton ? _backButton : _forwardButton; + + // Set the origin for the tools popup to the leading side of the bottom of the + // pressed buttons. + CGRect buttonBounds = [historyButton.imageView bounds]; + CGPoint leadingBottomCorner = CGPointMake(CGRectGetLeadingEdge(buttonBounds), + CGRectGetMaxY(buttonBounds)); + CGPoint origin = [historyButton.imageView convertPoint:leadingBottomCorner + toView:historyButton.window]; + return origin; +} + +- (void)updateUIForTabHistoryPresentationFrom:(ToolbarButton)button { + UIButton* historyButton = button ? _backButton : _forwardButton; + // Keep the button pressed by swapping the normal and highlighted images. + [self setImagesForNavButton:historyButton withTabHistoryVisible:YES]; +} + +- (void)updateUIForTabHistoryWasDismissed { + [self setImagesForNavButton:_backButton withTabHistoryVisible:NO]; + [self setImagesForNavButton:_forwardButton withTabHistoryVisible:NO]; +} + #pragma mark - #pragma mark DropAndNavigateDelegate
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm index 99d95529..f1669b5 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -139,7 +139,8 @@ } id<GREYMatcher> ToolsMenuButton() { - return ButtonWithAccessibilityLabelId(IDS_IOS_TOOLBAR_SETTINGS); + return grey_allOf(grey_accessibilityID(kToolbarToolsMenuButtonIdentifier), + grey_sufficientlyVisible(), nil); } id<GREYMatcher> ShareButton() {
diff --git a/net/BUILD.gn b/net/BUILD.gn index 1288ecc..016344d 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1280,8 +1280,6 @@ "quic/core/quic_client_promised_info.h", "quic/core/quic_client_push_promise_index.cc", "quic/core/quic_client_push_promise_index.h", - "quic/core/quic_client_session_base.cc", - "quic/core/quic_client_session_base.h", "quic/core/quic_config.cc", "quic/core/quic_config.h", "quic/core/quic_connection.cc", @@ -1342,6 +1340,8 @@ "quic/core/quic_simple_buffer_allocator.h", "quic/core/quic_socket_address_coder.cc", "quic/core/quic_socket_address_coder.h", + "quic/core/quic_spdy_client_session_base.cc", + "quic/core/quic_spdy_client_session_base.h", "quic/core/quic_spdy_session.cc", "quic/core/quic_spdy_session.h", "quic/core/quic_spdy_stream.cc", @@ -3010,6 +3010,8 @@ "tools/quic/platform/impl/quic_socket_utils.h", "tools/quic/quic_client.cc", "tools/quic/quic_client.h", + "tools/quic/quic_client_epoll_network_helper.cc", + "tools/quic/quic_client_epoll_network_helper.h", "tools/quic/quic_default_packet_writer.cc", "tools/quic/quic_default_packet_writer.h", "tools/quic/quic_epoll_alarm_factory.cc", @@ -3257,8 +3259,8 @@ "tools/quic/chlo_extractor.h", "tools/quic/quic_client_base.cc", "tools/quic/quic_client_base.h", - "tools/quic/quic_client_session.cc", - "tools/quic/quic_client_session.h", + "tools/quic/quic_client_message_loop_network_helper.cc", + "tools/quic/quic_client_message_loop_network_helper.h", "tools/quic/quic_dispatcher.cc", "tools/quic/quic_dispatcher.h", "tools/quic/quic_http_response_cache.cc", @@ -3284,6 +3286,10 @@ "tools/quic/quic_simple_server_session_helper.h", "tools/quic/quic_simple_server_stream.cc", "tools/quic/quic_simple_server_stream.h", + "tools/quic/quic_spdy_client_base.cc", + "tools/quic/quic_spdy_client_base.h", + "tools/quic/quic_spdy_client_session.cc", + "tools/quic/quic_spdy_client_session.h", "tools/quic/quic_spdy_client_stream.cc", "tools/quic/quic_spdy_client_stream.h", "tools/quic/quic_spdy_server_stream_base.cc", @@ -5297,7 +5303,6 @@ "tools/quic/end_to_end_test.cc", "tools/quic/platform/impl/quic_epoll_clock_test.cc", "tools/quic/platform/impl/quic_socket_utils_test.cc", - "tools/quic/quic_client_session_test.cc", "tools/quic/quic_client_test.cc", "tools/quic/quic_dispatcher_test.cc", "tools/quic/quic_epoll_alarm_factory_test.cc", @@ -5308,6 +5313,7 @@ "tools/quic/quic_simple_server_session_test.cc", "tools/quic/quic_simple_server_stream_test.cc", "tools/quic/quic_simple_server_test.cc", + "tools/quic/quic_spdy_client_session_test.cc", "tools/quic/quic_spdy_client_stream_test.cc", "tools/quic/quic_spdy_server_stream_base_test.cc", "tools/quic/quic_time_wait_list_manager_test.cc",
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc index 904f837f..d2a17ba 100644 --- a/net/quic/chromium/quic_chromium_client_session.cc +++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -592,7 +592,7 @@ base::TaskRunner* task_runner, std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher, NetLog* net_log) - : QuicClientSessionBase(connection, push_promise_index, config), + : QuicSpdyClientSessionBase(connection, push_promise_index, config), server_id_(server_id), require_confirmation_(require_confirmation), stream_factory_(stream_factory), @@ -758,7 +758,7 @@ } void QuicChromiumClientSession::Initialize() { - QuicClientSessionBase::Initialize(); + QuicSpdyClientSessionBase::Initialize(); SetHpackEncoderDebugVisitor( base::MakeUnique<HpackEncoderDebugVisitor>()); SetHpackDecoderDebugVisitor( @@ -1149,7 +1149,7 @@ } void QuicChromiumClientSession::OnConfigNegotiated() { - QuicClientSessionBase::OnConfigNegotiated(); + QuicSpdyClientSessionBase::OnConfigNegotiated(); if (!stream_factory_ || !config()->HasReceivedAlternateServerAddress()) return; @@ -1778,7 +1778,8 @@ bool QuicChromiumClientSession::HandlePromised(QuicStreamId id, QuicStreamId promised_id, const SpdyHeaderBlock& headers) { - bool result = QuicClientSessionBase::HandlePromised(id, promised_id, headers); + bool result = + QuicSpdyClientSessionBase::HandlePromised(id, promised_id, headers); if (result) { // The push promise is accepted, notify the push_delegate that a push // promise has been received. @@ -1799,7 +1800,7 @@ QuicClientPromisedInfo* promised) { if (IsOpenStream(promised->id())) streams_pushed_and_claimed_count_++; - QuicClientSessionBase::DeletePromised(promised); + QuicSpdyClientSessionBase::DeletePromised(promised); } void QuicChromiumClientSession::OnPushStreamTimedOut(QuicStreamId stream_id) { @@ -1810,7 +1811,7 @@ void QuicChromiumClientSession::CancelPush(const GURL& url) { QuicClientPromisedInfo* promised_info = - QuicClientSessionBase::GetPromisedByUrl(url.spec()); + QuicSpdyClientSessionBase::GetPromisedByUrl(url.spec()); if (!promised_info || promised_info->is_validating()) { // Push stream has already been claimed or is pending matched to a request. return; @@ -1824,7 +1825,7 @@ bytes_pushed_and_unclaimed_count_ += stream->stream_bytes_read(); // Send the reset and remove the promised info from the promise index. - QuicClientSessionBase::ResetPromised(stream_id, QUIC_STREAM_CANCELLED); + QuicSpdyClientSessionBase::ResetPromised(stream_id, QUIC_STREAM_CANCELLED); DeletePromised(promised_info); }
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h index 3b2102c..9a888bb 100644 --- a/net/quic/chromium/quic_chromium_client_session.h +++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -33,10 +33,10 @@ #include "net/quic/chromium/quic_chromium_packet_writer.h" #include "net/quic/chromium/quic_connection_logger.h" #include "net/quic/core/quic_client_push_promise_index.h" -#include "net/quic/core/quic_client_session_base.h" #include "net/quic/core/quic_crypto_client_stream.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_server_id.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/quic/core/quic_time.h" #include "net/socket/socket_performance_watcher.h" #include "net/spdy/chromium/multiplexed_session.h" @@ -62,7 +62,7 @@ } // namespace test class NET_EXPORT_PRIVATE QuicChromiumClientSession - : public QuicClientSessionBase, + : public QuicSpdyClientSessionBase, public MultiplexedSession, public QuicChromiumPacketReader::Visitor, public QuicChromiumPacketWriter::Delegate {
diff --git a/net/quic/chromium/quic_chromium_client_stream.cc b/net/quic/chromium/quic_chromium_client_stream.cc index 029cd4d8..f765b19 100644 --- a/net/quic/chromium/quic_chromium_client_stream.cc +++ b/net/quic/chromium/quic_chromium_client_stream.cc
@@ -389,7 +389,7 @@ QuicChromiumClientStream::QuicChromiumClientStream( QuicStreamId id, - QuicClientSessionBase* session, + QuicSpdyClientSessionBase* session, const NetLogWithSource& net_log) : QuicSpdyStream(id, session), net_log_(net_log),
diff --git a/net/quic/chromium/quic_chromium_client_stream.h b/net/quic/chromium/quic_chromium_client_stream.h index 80a84b17..92dfa30 100644 --- a/net/quic/chromium/quic_chromium_client_stream.h +++ b/net/quic/chromium/quic_chromium_client_stream.h
@@ -26,7 +26,7 @@ namespace net { -class QuicClientSessionBase; +class QuicSpdyClientSessionBase; // A client-initiated ReliableQuicStream. Instances of this class // are owned by the QuicClientSession which created them. @@ -190,7 +190,7 @@ }; QuicChromiumClientStream(QuicStreamId id, - QuicClientSessionBase* session, + QuicSpdyClientSessionBase* session, const NetLogWithSource& net_log); ~QuicChromiumClientStream() override; @@ -273,7 +273,7 @@ // True when initial headers have been sent. bool initial_headers_sent_; - QuicClientSessionBase* session_; + QuicSpdyClientSessionBase* session_; // Set to false if this stream to not be migrated during connection migration. bool can_migrate_;
diff --git a/net/quic/chromium/quic_chromium_client_stream_test.cc b/net/quic/chromium/quic_chromium_client_stream_test.cc index dab3390..62431ae1 100644 --- a/net/quic/chromium/quic_chromium_client_stream_test.cc +++ b/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -13,7 +13,7 @@ #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/quic/chromium/quic_chromium_client_session.h" -#include "net/quic/core/quic_client_session_base.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_ptr_util.h" @@ -38,7 +38,7 @@ const QuicStreamId kTestStreamId = 5u; -class MockQuicClientSessionBase : public QuicClientSessionBase { +class MockQuicClientSessionBase : public QuicSpdyClientSessionBase { public: explicit MockQuicClientSessionBase(QuicConnection* connection, QuicClientPushPromiseIndex* index); @@ -142,9 +142,9 @@ MockQuicClientSessionBase::MockQuicClientSessionBase( QuicConnection* connection, QuicClientPushPromiseIndex* push_promise_index) - : QuicClientSessionBase(connection, - push_promise_index, - DefaultQuicConfig()) { + : QuicSpdyClientSessionBase(connection, + push_promise_index, + DefaultQuicConfig()) { crypto_stream_.reset(new MockQuicCryptoStream(this)); Initialize(); ON_CALL(*this, WritevData(_, _, _, _, _, _))
diff --git a/net/quic/chromium/quic_test_packet_maker.cc b/net/quic/chromium/quic_test_packet_maker.cc index 6a692ec..23a40b5 100644 --- a/net/quic/chromium/quic_test_packet_maker.cc +++ b/net/quic/chromium/quic_test_packet_maker.cc
@@ -99,7 +99,7 @@ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now())); } if (largest_received > 0) { - ack.packets.Add(1, largest_received + 1); + ack.packets.AddRange(1, largest_received + 1); } QuicFrames frames; frames.push_back(QuicFrame(&ack)); @@ -148,7 +148,7 @@ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now())); } if (largest_received > 0) { - ack.packets.Add(1, largest_received + 1); + ack.packets.AddRange(1, largest_received + 1); } QuicFrames frames; frames.push_back(QuicFrame(&ack)); @@ -242,7 +242,7 @@ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now())); } if (largest_received > 0) { - ack.packets.Add(1, largest_received + 1); + ack.packets.AddRange(1, largest_received + 1); } QuicFramer framer(SupportedVersions(version_), clock_->Now(), perspective_); @@ -324,7 +324,7 @@ ack.received_packet_times.push_back(std::make_pair(i, clock_->Now())); } if (largest_received > 0) { - ack.packets.Add(1, largest_received + 1); + ack.packets.AddRange(1, largest_received + 1); } QuicFrames frames; frames.push_back(QuicFrame(&ack));
diff --git a/net/quic/core/crypto/crypto_framer_test.cc b/net/quic/core/crypto/crypto_framer_test.cc index 846f91f4..9d61aa4e 100644 --- a/net/quic/core/crypto/crypto_framer_test.cc +++ b/net/quic/core/crypto/crypto_framer_test.cc
@@ -47,6 +47,11 @@ std::vector<CryptoHandshakeMessage> messages_; }; +INSTANTIATE_TEST_CASE_P(Tests, + CryptoFramerTest, + ::testing::ValuesIn({Perspective::IS_CLIENT, + Perspective::IS_SERVER})); + TEST_P(CryptoFramerTest, ConstructHandshakeMessage) { CryptoHandshakeMessage message; message.set_tag(0xFFAA7733);
diff --git a/net/quic/core/crypto/crypto_handshake_message_test.cc b/net/quic/core/crypto/crypto_handshake_message_test.cc index a44e64a..1f5660b9 100644 --- a/net/quic/core/crypto/crypto_handshake_message_test.cc +++ b/net/quic/core/crypto/crypto_handshake_message_test.cc
@@ -6,6 +6,7 @@ #include "net/quic/core/crypto/crypto_handshake.h" #include "net/quic/core/crypto/crypto_protocol.h" +#include "net/quic/platform/api/quic_endian.h" #include "net/quic/platform/api/quic_test.h" namespace net { @@ -14,6 +15,11 @@ class CryptoHandshakeMessageTest : public QuicTestWithParam<Perspective> {}; +INSTANTIATE_TEST_CASE_P(Perspective, + CryptoHandshakeMessageTest, + ::testing::ValuesIn({Perspective::IS_CLIENT, + Perspective::IS_SERVER})); + TEST_P(CryptoHandshakeMessageTest, DebugString) { const char* str = "SHLO<\n>"; @@ -99,7 +105,8 @@ CryptoHandshakeMessage message; message.set_tag(kSREJ); - message.SetValue(kRCID, UINT64_C(18364758544493064720)); + message.SetValue(kRCID, + QuicEndian::NetToHost64(UINT64_C(18364758544493064720))); EXPECT_EQ(str, message.DebugString(GetParam())); // Test copy
diff --git a/net/quic/core/crypto/crypto_protocol.h b/net/quic/core/crypto/crypto_protocol.h index e681283..c408070 100644 --- a/net/quic/core/crypto/crypto_protocol.h +++ b/net/quic/core/crypto/crypto_protocol.h
@@ -115,6 +115,8 @@ // with 1/8 RTT acks. const QuicTag kAKD4 = TAG('A', 'K', 'D', '4'); // Ack decimation with 1/8 RTT // tolerating out of order. +const QuicTag kAKDU = TAG('A', 'K', 'D', 'U'); // Unlimited number of packets + // receieved before acking const QuicTag kSSLR = TAG('S', 'S', 'L', 'R'); // Slow Start Large Reduction. const QuicTag kNPRR = TAG('N', 'P', 'R', 'R'); // Pace at unity instead of PRR const QuicTag k5RTO = TAG('5', 'R', 'T', 'O'); // Close connection on 5 RTOs
diff --git a/net/quic/core/frames/quic_ack_frame.cc b/net/quic/core/frames/quic_ack_frame.cc index a86f6d0..385500a7 100644 --- a/net/quic/core/frames/quic_ack_frame.cc +++ b/net/quic/core/frames/quic_ack_frame.cc
@@ -90,27 +90,30 @@ Interval<QuicPacketNumber>(packet_number, packet_number + 1)); return; } + Interval<QuicPacketNumber> back = packet_number_deque_.back(); // Check for the typical case, // when the next packet in order is acked - if ((packet_number_deque_.back()).max() == packet_number) { - (packet_number_deque_.back()).SetMax(packet_number + 1); + if (back.max() == packet_number) { + packet_number_deque_.back().SetMax(packet_number + 1); return; } // Check if the next packet in order is skipped - if ((packet_number_deque_.back()).max() < packet_number) { + if (back.max() < packet_number) { packet_number_deque_.push_back( Interval<QuicPacketNumber>(packet_number, packet_number + 1)); return; } + + Interval<QuicPacketNumber> front = packet_number_deque_.front(); // Check if the packet can be popped on the front - if ((packet_number_deque_.front()).min() > packet_number + 1) { + if (front.min() > packet_number + 1) { packet_number_deque_.push_front( Interval<QuicPacketNumber>(packet_number, packet_number + 1)); return; } - if ((packet_number_deque_.front()).min() == packet_number + 1) { - (packet_number_deque_.front()).SetMin(packet_number); + if (front.min() == packet_number + 1) { + packet_number_deque_.front().SetMin(packet_number); return; } @@ -118,36 +121,35 @@ // Iterating through the queue backwards // to find a proper place for the packet while (i >= 0) { + Interval<QuicPacketNumber> packet_interval = packet_number_deque_[i]; // Check if the packet is contained in an interval already - if (packet_number_deque_[i].max() > packet_number && - packet_number_deque_[i].min() <= packet_number) { + if (packet_interval.max() > packet_number && + packet_interval.min() <= packet_number) { return; } // Check if the packet can extend an interval // and merges two intervals if needed - if (packet_number_deque_[i].max() == packet_number) { + if (packet_interval.max() == packet_number) { packet_number_deque_[i].SetMax(packet_number + 1); if (static_cast<size_t>(i) < packet_number_deque_.size() - 1 && - packet_number_deque_[i].max() == - packet_number_deque_[i + 1].min()) { + packet_number + 1 == packet_number_deque_[i + 1].min()) { packet_number_deque_[i].SetMax(packet_number_deque_[i + 1].max()); packet_number_deque_.erase(packet_number_deque_.begin() + i + 1); } return; } - if (packet_number_deque_[i].min() == packet_number + 1) { + if (packet_interval.min() == packet_number + 1) { packet_number_deque_[i].SetMin(packet_number); - if (i > 0 && packet_number_deque_[i].min() == - packet_number_deque_[i - 1].max()) { - packet_number_deque_[i - 1].SetMax(packet_number_deque_[i].max()); + if (i > 0 && packet_number == packet_number_deque_[i - 1].max()) { + packet_number_deque_[i - 1].SetMax(packet_interval.max()); packet_number_deque_.erase(packet_number_deque_.begin() + i); } return; } // Check if we need to make a new interval for the packet - if (packet_number_deque_[i].max() < packet_number + 1) { + if (packet_interval.max() < packet_number + 1) { packet_number_deque_.insert( packet_number_deque_.begin() + i + 1, Interval<QuicPacketNumber>(packet_number, packet_number + 1)); @@ -160,7 +162,8 @@ } } -void PacketNumberQueue::Add(QuicPacketNumber lower, QuicPacketNumber higher) { +void PacketNumberQueue::AddRange(QuicPacketNumber lower, + QuicPacketNumber higher) { if (lower >= higher) { return; } @@ -168,26 +171,47 @@ if (packet_number_deque_.empty()) { packet_number_deque_.push_front( Interval<QuicPacketNumber>(lower, higher)); + return; + } + Interval<QuicPacketNumber> back = packet_number_deque_.back(); - } else if ((packet_number_deque_.back()).max() == lower) { + if (back.max() == lower) { // Check for the typical case, // when the next packet in order is acked - (packet_number_deque_.back()).SetMax(higher); - - } else if ((packet_number_deque_.back()).max() < lower) { + packet_number_deque_.back().SetMax(higher); + return; + } + if (back.max() < lower) { // Check if the next packet in order is skipped packet_number_deque_.push_back(Interval<QuicPacketNumber>(lower, higher)); - - // Check if the packets are being added in reverse order - } else if ((packet_number_deque_.front()).min() == higher) { - (packet_number_deque_.front()).SetMax(lower); - } else if ((packet_number_deque_.front()).min() > higher) { + return; + } + Interval<QuicPacketNumber> front = packet_number_deque_.front(); + // Check if the packets are being added in reverse order + if (front.min() == higher) { + packet_number_deque_.front().SetMax(lower); + } else if (front.min() > higher) { packet_number_deque_.push_front( Interval<QuicPacketNumber>(lower, higher)); } else { // Iterating through the interval and adding packets one by one - for (size_t i = lower; i != higher; i++) { + QUIC_BUG << "In the slowpath of AddRange. Adding [" << lower << ", " + << higher << "), in a deque of size " + << packet_number_deque_.size() << ", whose largest element is " + << back.max() << " and smallest " << front.min() << ".\n"; + // Check if the first and/or the last interval of the deque can be + // extended, which would reduce the compexity of the following for loop. + if (higher >= back.max()) { + packet_number_deque_.back().SetMax(higher); + higher = back.min(); + } + if (lower < front.min()) { + packet_number_deque_.front().SetMin(lower); + lower = front.max() - 1; + } + + for (size_t i = lower; i < higher; i++) { PacketNumberQueue::Add(i); } } @@ -203,13 +227,12 @@ const QuicPacketNumber old_min = Min(); if (use_deque_) { while (!packet_number_deque_.empty()) { - if (packet_number_deque_.front().max() < higher) { + Interval<QuicPacketNumber> front = packet_number_deque_.front(); + if (front.max() < higher) { packet_number_deque_.pop_front(); - } else if (packet_number_deque_.front().min() < higher && - packet_number_deque_.front().max() >= higher) { + } else if (front.min() < higher && front.max() >= higher) { packet_number_deque_.front().SetMin(higher); - if (packet_number_deque_.front().max() == - packet_number_deque_.front().min()) { + if (front.max() == higher) { packet_number_deque_.pop_front(); } break; @@ -243,22 +266,14 @@ if (packet_number_deque_.empty()) { return false; } - int low = 0; - int high = packet_number_deque_.size() - 1; - - while (low <= high) { - int mid = (low + high) / 2; - if (packet_number_deque_[mid].min() > packet_number) { - high = mid - 1; - continue; + if (packet_number_deque_.front().min() > packet_number || + packet_number_deque_.back().max() <= packet_number) { + return false; + } + for (Interval<QuicPacketNumber> interval : packet_number_deque_) { + if (interval.Contains(packet_number)) { + return true; } - if (packet_number_deque_[mid].max() <= packet_number) { - low = mid + 1; - continue; - } - DCHECK(packet_number_deque_[mid].max() > packet_number); - DCHECK(packet_number_deque_[mid].min() <= packet_number); - return true; } return false; } else { @@ -294,9 +309,9 @@ size_t PacketNumberQueue::NumPacketsSlow() const { if (use_deque_) { - size_t n_packets = 0; - for (size_t i = 0; i < packet_number_deque_.size(); i++) { - n_packets += packet_number_deque_[i].Length(); + int n_packets = 0; + for (Interval<QuicPacketNumber> interval : packet_number_deque_) { + n_packets += interval.Length(); } return n_packets; } else { @@ -351,7 +366,7 @@ QuicPacketNumber PacketNumberQueue::LastIntervalLength() const { DCHECK(!Empty()); if (use_deque_) { - return packet_number_deque_[packet_number_deque_.size() - 1].Length(); + return packet_number_deque_.back().Length(); } else { return packet_number_intervals_.rbegin()->Length(); }
diff --git a/net/quic/core/frames/quic_ack_frame.h b/net/quic/core/frames/quic_ack_frame.h index c7584c1..f8b9ef0 100644 --- a/net/quic/core/frames/quic_ack_frame.h +++ b/net/quic/core/frames/quic_ack_frame.h
@@ -198,7 +198,7 @@ // Adds packets between [lower, higher) to the set of packets in the queue. It // is undefined behavior to call this with |higher| < |lower|. - void Add(QuicPacketNumber lower, QuicPacketNumber higher); + void AddRange(QuicPacketNumber lower, QuicPacketNumber higher); // Removes packets with values less than |higher| from the set of packets in // the queue. Returns true if packets were removed.
diff --git a/net/quic/core/frames/quic_frames_test.cc b/net/quic/core/frames/quic_frames_test.cc index 70cbfcb3..9312e58 100644 --- a/net/quic/core/frames/quic_frames_test.cc +++ b/net/quic/core/frames/quic_frames_test.cc
@@ -15,6 +15,7 @@ #include "net/quic/core/frames/quic_stream_frame.h" #include "net/quic/core/frames/quic_window_update_frame.h" #include "net/quic/platform/api/quic_test.h" +#include "net/quic/test_tools/quic_test_utils.h" namespace net { namespace test { @@ -117,7 +118,7 @@ TEST_F(QuicFramesTest, IsAwaitingPacket) { QuicAckFrame ack_frame1; ack_frame1.largest_observed = 10u; - ack_frame1.packets.Add(1, 11); + ack_frame1.packets.AddRange(1, 11); EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 11u, 0u)); EXPECT_FALSE(IsAwaitingPacket(ack_frame1, 1u, 0u)); @@ -126,12 +127,12 @@ QuicAckFrame ack_frame2; ack_frame2.largest_observed = 100u; - ack_frame2.packets.Add(21, 100); + ack_frame2.packets.AddRange(21, 100); EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 11u, 20u)); EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 80u, 20u)); EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u)); - ack_frame2.packets.Add(102, 200); + ack_frame2.packets.AddRange(102, 200); EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u)); } @@ -207,8 +208,8 @@ TEST_F(QuicFramesTest, AddInterval) { QuicAckFrame ack_frame1; - ack_frame1.packets.Add(1, 10); - ack_frame1.packets.Add(50, 100); + ack_frame1.packets.AddRange(1, 10); + ack_frame1.packets.AddRange(50, 100); EXPECT_EQ(2u, ack_frame1.packets.NumIntervals()); EXPECT_EQ(1u, ack_frame1.packets.Min()); @@ -223,7 +224,12 @@ EXPECT_EQ(expected_intervals, actual_intervals); - ack_frame1.packets.Add(20, 30); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(20, 30), ""); + } else { + ack_frame1.packets.AddRange(20, 30); + } + const std::vector<Interval<QuicPacketNumber>> actual_intervals2( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -235,8 +241,13 @@ EXPECT_EQ(3u, ack_frame1.packets.NumIntervals()); EXPECT_EQ(expected_intervals2, actual_intervals2); - ack_frame1.packets.Add(15, 20); - ack_frame1.packets.Add(30, 35); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(15, 20), ""); + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(30, 35), ""); + } else { + ack_frame1.packets.AddRange(15, 20); + ack_frame1.packets.AddRange(30, 35); + } const std::vector<Interval<QuicPacketNumber>> actual_intervals3( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -248,15 +259,23 @@ EXPECT_EQ(expected_intervals3, actual_intervals3); - ack_frame1.packets.Add(20, 35); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(20, 35), ""); + } else { + ack_frame1.packets.AddRange(20, 35); + } const std::vector<Interval<QuicPacketNumber>> actual_intervals4( ack_frame1.packets.begin(), ack_frame1.packets.end()); EXPECT_EQ(expected_intervals3, actual_intervals4); - - ack_frame1.packets.Add(12, 20); - ack_frame1.packets.Add(30, 38); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(12, 20), ""); + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(30, 38), ""); + } else { + ack_frame1.packets.AddRange(12, 20); + ack_frame1.packets.AddRange(30, 38); + } const std::vector<Interval<QuicPacketNumber>> actual_intervals5( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -267,8 +286,11 @@ expected_intervals5.push_back(Interval<QuicPacketNumber>(50, 100)); EXPECT_EQ(expected_intervals5, actual_intervals5); - - ack_frame1.packets.Add(8, 55); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(8, 55), ""); + } else { + ack_frame1.packets.AddRange(8, 55); + } const std::vector<Interval<QuicPacketNumber>> actual_intervals6( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -278,7 +300,11 @@ EXPECT_EQ(expected_intervals6, actual_intervals6); - ack_frame1.packets.Add(0, 200); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(0, 200), ""); + } else { + ack_frame1.packets.AddRange(0, 200); + } const std::vector<Interval<QuicPacketNumber>> actual_intervals7( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -289,11 +315,11 @@ EXPECT_EQ(expected_intervals7, actual_intervals7); QuicAckFrame ack_frame2; - ack_frame2.packets.Add(20, 25); - ack_frame2.packets.Add(40, 45); - ack_frame2.packets.Add(60, 65); - ack_frame2.packets.Add(10, 15); - ack_frame2.packets.Add(80, 85); + ack_frame2.packets.AddRange(20, 25); + ack_frame2.packets.AddRange(40, 45); + ack_frame2.packets.AddRange(60, 65); + ack_frame2.packets.AddRange(10, 15); + ack_frame2.packets.AddRange(80, 85); const std::vector<Interval<QuicPacketNumber>> actual_intervals8( ack_frame2.packets.begin(), ack_frame2.packets.end()); @@ -308,12 +334,85 @@ EXPECT_EQ(expected_intervals8, actual_intervals8); } +TEST_F(QuicFramesTest, AddIntervalBig) { + QuicAckFrame ack_frame1; + ack_frame1.packets.AddRange(20, 30); + ack_frame1.packets.AddRange(70, 100); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(56, 58), ""); + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(65, 69), ""); + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(59, 64), ""); + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(50, 55), ""); + } else { + ack_frame1.packets.AddRange(56, 58); + ack_frame1.packets.AddRange(65, 69); + ack_frame1.packets.AddRange(59, 64); + ack_frame1.packets.AddRange(50, 55); + } + + std::vector<Interval<QuicPacketNumber>> expected_intervals; + expected_intervals.push_back(Interval<QuicPacketNumber>(20, 30)); + expected_intervals.push_back(Interval<QuicPacketNumber>(50, 55)); + expected_intervals.push_back(Interval<QuicPacketNumber>(56, 58)); + expected_intervals.push_back(Interval<QuicPacketNumber>(59, 64)); + expected_intervals.push_back(Interval<QuicPacketNumber>(65, 69)); + expected_intervals.push_back(Interval<QuicPacketNumber>(70, 100)); + + const std::vector<Interval<QuicPacketNumber>> actual_intervals( + ack_frame1.packets.begin(), ack_frame1.packets.end()); + + EXPECT_EQ(expected_intervals, actual_intervals); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(10, 60), ""); + } else { + ack_frame1.packets.AddRange(10, 60); + } + + std::vector<Interval<QuicPacketNumber>> expected_intervals2; + expected_intervals2.push_back(Interval<QuicPacketNumber>(10, 64)); + expected_intervals2.push_back(Interval<QuicPacketNumber>(65, 69)); + expected_intervals2.push_back(Interval<QuicPacketNumber>(70, 100)); + + const std::vector<Interval<QuicPacketNumber>> actual_intervals2( + ack_frame1.packets.begin(), ack_frame1.packets.end()); + + EXPECT_EQ(expected_intervals2, actual_intervals2); + + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(68, 1000), ""); + } else { + ack_frame1.packets.AddRange(68, 1000); + } + + std::vector<Interval<QuicPacketNumber>> expected_intervals3; + expected_intervals3.push_back(Interval<QuicPacketNumber>(10, 64)); + expected_intervals3.push_back(Interval<QuicPacketNumber>(65, 1000)); + + const std::vector<Interval<QuicPacketNumber>> actual_intervals3( + ack_frame1.packets.begin(), ack_frame1.packets.end()); + + EXPECT_EQ(expected_intervals3, actual_intervals3); + if (FLAGS_quic_reloadable_flag_quic_frames_deque) { + EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(0, 10000), ""); + } else { + ack_frame1.packets.AddRange(0, 10000); + } + + std::vector<Interval<QuicPacketNumber>> expected_intervals4; + expected_intervals4.push_back(Interval<QuicPacketNumber>(0, 10000)); + + const std::vector<Interval<QuicPacketNumber>> actual_intervals4( + ack_frame1.packets.begin(), ack_frame1.packets.end()); + + EXPECT_EQ(expected_intervals4, actual_intervals4); +} + TEST_F(QuicFramesTest, RemoveSmallestInterval) { QuicAckFrame ack_frame1; ack_frame1.largest_observed = 100u; - ack_frame1.packets.Add(51, 60); - ack_frame1.packets.Add(71, 80); - ack_frame1.packets.Add(91, 100); + ack_frame1.packets.AddRange(51, 60); + ack_frame1.packets.AddRange(71, 80); + ack_frame1.packets.AddRange(91, 100); ack_frame1.packets.RemoveSmallestInterval(); EXPECT_EQ(2u, ack_frame1.packets.NumIntervals()); EXPECT_EQ(71u, ack_frame1.packets.Min()); @@ -330,7 +429,7 @@ // Tests that a queue contains the expected data after calls to Add(). TEST_F(PacketNumberQueueTest, AddRange) { PacketNumberQueue queue; - queue.Add(1, 51); + queue.AddRange(1, 51); queue.Add(53); EXPECT_FALSE(queue.Contains(0)); @@ -353,7 +452,7 @@ TEST_F(PacketNumberQueueTest, Contains) { PacketNumberQueue queue; EXPECT_FALSE(queue.Contains(0)); - queue.Add(5, 10); + queue.AddRange(5, 10); queue.Add(20); for (int i = 1; i < 5; ++i) { @@ -389,7 +488,7 @@ TEST_F(PacketNumberQueueTest, Removal) { PacketNumberQueue queue; EXPECT_FALSE(queue.Contains(51)); - queue.Add(0, 100); + queue.AddRange(0, 100); EXPECT_TRUE(queue.RemoveUpTo(51)); EXPECT_FALSE(queue.RemoveUpTo(51)); @@ -406,7 +505,7 @@ EXPECT_EQ(99u, queue.Max()); PacketNumberQueue queue2; - queue2.Add(0, 5); + queue2.AddRange(0, 5); EXPECT_TRUE(queue2.RemoveUpTo(3)); EXPECT_TRUE(queue2.RemoveUpTo(50)); EXPECT_TRUE(queue2.Empty()); @@ -418,7 +517,7 @@ EXPECT_TRUE(queue.Empty()); EXPECT_EQ(0u, queue.NumPacketsSlow()); - queue.Add(1, 100); + queue.AddRange(1, 100); EXPECT_TRUE(queue.RemoveUpTo(100)); EXPECT_TRUE(queue.Empty()); EXPECT_EQ(0u, queue.NumPacketsSlow()); @@ -431,21 +530,21 @@ oss << queue; queue.Add(1); - queue.Add(50, 100); + queue.AddRange(50, 100); oss << queue; } // Tests that the iterators returned from a packet queue iterate over the queue. TEST_F(PacketNumberQueueTest, Iterators) { PacketNumberQueue queue; - queue.Add(1, 100); + queue.AddRange(1, 100); const std::vector<Interval<QuicPacketNumber>> actual_intervals(queue.begin(), queue.end()); PacketNumberQueue queue2; for (int i = 1; i < 100; i++) { - queue2.Add(i, i + 1); + queue2.AddRange(i, i + 1); } const std::vector<Interval<QuicPacketNumber>> actual_intervals2( @@ -460,10 +559,10 @@ TEST_F(PacketNumberQueueTest, ReversedIterators) { PacketNumberQueue queue; - queue.Add(1, 100); + queue.AddRange(1, 100); PacketNumberQueue queue2; for (int i = 1; i < 100; i++) { - queue2.Add(i, i + 1); + queue2.AddRange(i, i + 1); } const std::vector<Interval<QuicPacketNumber>> actual_intervals(queue.rbegin(), queue.rend()); @@ -495,9 +594,9 @@ TEST_F(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) { PacketNumberQueue queue; - queue.Add(1, 10); - queue.Add(20, 30); - queue.Add(40, 50); + queue.AddRange(1, 10); + queue.AddRange(20, 30); + queue.AddRange(40, 50); EXPECT_EQ(3u, queue.NumIntervals()); EXPECT_EQ(10u, queue.LastIntervalLength());
diff --git a/net/quic/core/quic_client_promised_info.cc b/net/quic/core/quic_client_promised_info.cc index ebc6d18..a8241ec 100644 --- a/net/quic/core/quic_client_promised_info.cc +++ b/net/quic/core/quic_client_promised_info.cc
@@ -11,9 +11,10 @@ namespace net { -QuicClientPromisedInfo::QuicClientPromisedInfo(QuicClientSessionBase* session, - QuicStreamId id, - string url) +QuicClientPromisedInfo::QuicClientPromisedInfo( + QuicSpdyClientSessionBase* session, + QuicStreamId id, + string url) : session_(session), id_(id), url_(std::move(url)),
diff --git a/net/quic/core/quic_client_promised_info.h b/net/quic/core/quic_client_promised_info.h index 1f755fe..1946956e 100644 --- a/net/quic/core/quic_client_promised_info.h +++ b/net/quic/core/quic_client_promised_info.h
@@ -10,16 +10,14 @@ #include "net/quic/core/quic_alarm.h" #include "net/quic/core/quic_client_push_promise_index.h" -#include "net/quic/core/quic_client_session_base.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/quic/core/quic_spdy_stream.h" #include "net/quic/platform/api/quic_export.h" #include "net/spdy/core/spdy_framer.h" namespace net { -class QuicClientSessionBase; - namespace test { class QuicClientPromisedInfoPeer; } // namespace test @@ -32,7 +30,7 @@ : public QuicClientPushPromiseIndex::TryHandle { public: // Interface to QuicSpdyClientStream - QuicClientPromisedInfo(QuicClientSessionBase* session, + QuicClientPromisedInfo(QuicSpdyClientSessionBase* session, QuicStreamId id, std::string url); virtual ~QuicClientPromisedInfo(); @@ -60,7 +58,7 @@ // uing the |promised_by_url| map. The push can be cross-origin, so // the client should validate that the session is authoritative for // the promised URL. If not, it should call |RejectUnauthorized|. - QuicClientSessionBase* session() { return session_; } + QuicSpdyClientSessionBase* session() { return session_; } // If the promised response contains Vary header, then the fields // specified by Vary must match between the client request header @@ -94,7 +92,7 @@ QuicAsyncStatus FinalValidation(); - QuicClientSessionBase* session_; + QuicSpdyClientSessionBase* session_; QuicStreamId id_; std::string url_; std::unique_ptr<SpdyHeaderBlock> request_headers_;
diff --git a/net/quic/core/quic_client_promised_info_test.cc b/net/quic/core/quic_client_promised_info_test.cc index 954f21b..70d0ac6 100644 --- a/net/quic/core/quic_client_promised_info_test.cc +++ b/net/quic/core/quic_client_promised_info_test.cc
@@ -15,7 +15,7 @@ #include "net/quic/test_tools/quic_client_promised_info_peer.h" #include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/test/gtest_util.h" -#include "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_spdy_client_session.h" using std::string; using testing::StrictMock; @@ -24,11 +24,12 @@ namespace test { namespace { -class MockQuicClientSession : public QuicClientSession { +class MockQuicSpdyClientSession : public QuicSpdyClientSession { public: - explicit MockQuicClientSession(QuicConnection* connection, - QuicClientPushPromiseIndex* push_promise_index) - : QuicClientSession( + explicit MockQuicSpdyClientSession( + QuicConnection* connection, + QuicClientPushPromiseIndex* push_promise_index) + : QuicSpdyClientSession( DefaultQuicConfig(), connection, QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED), @@ -36,7 +37,7 @@ push_promise_index), crypto_config_(crypto_test_utils::ProofVerifierForTesting()), authorized_(true) {} - ~MockQuicClientSession() override {} + ~MockQuicSpdyClientSession() override {} bool IsAuthorized(const string& authority) override { return authorized_; } @@ -49,7 +50,7 @@ bool authorized_; - DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession); + DISALLOW_COPY_AND_ASSIGN(MockQuicSpdyClientSession); }; class QuicClientPromisedInfoTest : public QuicTest { @@ -104,7 +105,7 @@ StrictMock<MockQuicConnection>* connection_; QuicClientPushPromiseIndex push_promise_index_; - MockQuicClientSession session_; + MockQuicSpdyClientSession session_; std::unique_ptr<QuicSpdyClientStream> stream_; std::unique_ptr<StreamVisitor> stream_visitor_; std::unique_ptr<QuicSpdyClientStream> promised_stream_;
diff --git a/net/quic/core/quic_client_push_promise_index.h b/net/quic/core/quic_client_push_promise_index.h index 38dc1fc8..2609ae1 100644 --- a/net/quic/core/quic_client_push_promise_index.h +++ b/net/quic/core/quic_client_push_promise_index.h
@@ -7,7 +7,7 @@ #include <string> -#include "net/quic/core/quic_client_session_base.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/quic/core/quic_types.h" #include "net/quic/platform/api/quic_export.h"
diff --git a/net/quic/core/quic_client_push_promise_index_test.cc b/net/quic/core/quic_client_push_promise_index_test.cc index 0a93cf1..9f980f14 100644 --- a/net/quic/core/quic_client_push_promise_index_test.cc +++ b/net/quic/core/quic_client_push_promise_index_test.cc
@@ -12,36 +12,37 @@ #include "net/quic/test_tools/mock_quic_client_promised_info.h" #include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_spdy_client_session.h" -using testing::_; using testing::Return; using testing::StrictMock; +using testing::_; using std::string; namespace net { namespace test { namespace { -class MockQuicClientSession : public QuicClientSession { +class MockQuicSpdyClientSession : public QuicSpdyClientSession { public: - explicit MockQuicClientSession(QuicConnection* connection, - QuicClientPushPromiseIndex* push_promise_index) - : QuicClientSession( + explicit MockQuicSpdyClientSession( + QuicConnection* connection, + QuicClientPushPromiseIndex* push_promise_index) + : QuicSpdyClientSession( DefaultQuicConfig(), connection, QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED), &crypto_config_, push_promise_index), crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {} - ~MockQuicClientSession() override {} + ~MockQuicSpdyClientSession() override {} MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id)); private: QuicCryptoClientConfig crypto_config_; - DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession); + DISALLOW_COPY_AND_ASSIGN(MockQuicSpdyClientSession); }; class QuicClientPushPromiseIndexTest : public QuicTest { @@ -66,7 +67,7 @@ MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; StrictMock<MockQuicConnection>* connection_; - MockQuicClientSession session_; + MockQuicSpdyClientSession session_; QuicClientPushPromiseIndex index_; SpdyHeaderBlock request_; string url_;
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc index 019d15a..e1f2cbbd 100644 --- a/net/quic/core/quic_connection.cc +++ b/net/quic/core/quic_connection.cc
@@ -216,6 +216,7 @@ stop_waiting_count_(0), ack_mode_(TCP_ACKING), ack_decimation_delay_(kAckDecimationDelay), + unlimited_ack_decimation_(false), delay_setting_retransmission_alarm_(false), pending_retransmission_alarm_(false), defer_send_in_response_to_packets_(false), @@ -270,7 +271,7 @@ largest_received_packet_size_(0), goaway_sent_(false), goaway_received_(false), - write_error_occured_(false), + write_error_occurred_(false), no_stop_waiting_frames_(false), consecutive_num_packets_with_no_retransmittable_frames_(0) { QUIC_DLOG(INFO) << ENDPOINT @@ -354,6 +355,12 @@ ack_mode_ = ACK_DECIMATION_WITH_REORDERING; ack_decimation_delay_ = kShortAckDecimationDelay; } + if (FLAGS_quic_reloadable_flag_quic_ack_decimation) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_ack_decimation); + if (config.HasClientSentConnectionOption(kAKDU, perspective_)) { + unlimited_ack_decimation_ = true; + } + } if (config.HasClientSentConnectionOption(k5RTO, perspective_)) { close_connection_after_five_rtos_ = true; } @@ -974,9 +981,10 @@ ++num_retransmittable_packets_received_since_last_ack_sent_; if (ack_mode_ != TCP_ACKING && last_header_.packet_number > kMinReceivedBeforeAckDecimation) { - // Ack up to 10 packets at once. - if (num_retransmittable_packets_received_since_last_ack_sent_ >= - kMaxRetransmittablePacketsBeforeAck) { + // Ack up to 10 packets at once unless ack decimation is unlimited. + if (!unlimited_ack_decimation_ && + num_retransmittable_packets_received_since_last_ack_sent_ >= + kMaxRetransmittablePacketsBeforeAck) { ack_queued_ = true; } else if (!ack_alarm_->IsSet()) { // Wait the minimum of a quarter min_rtt and the delayed ack time. @@ -1639,11 +1647,11 @@ } void QuicConnection::OnWriteError(int error_code) { - if (write_error_occured_) { + if (write_error_occurred_) { // A write error already occurred. The connection is being closed. return; } - write_error_occured_ = true; + write_error_occurred_ = true; const string error_details = QuicStrCat( "Write failed with error: ", error_code, " (", strerror(error_code), ")");
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h index 30c58fa..80c76bb 100644 --- a/net/quic/core/quic_connection.h +++ b/net/quic/core/quic_connection.h
@@ -960,6 +960,9 @@ AckMode ack_mode_; // The max delay in fraction of min_rtt to use when sending decimated acks. float ack_decimation_delay_; + // When true, removes ack decimation's max number of packets(10) before + // sending an ack. + bool unlimited_ack_decimation_; // Indicates the retransmit alarm is going to be set by the // ScopedRetransmitAlarmDelayer @@ -1095,7 +1098,7 @@ // Indicates whether a write error is encountered currently. This is used to // avoid infinite write errors. - bool write_error_occured_; + bool write_error_occurred_; // Indicates not to send or process stop waiting frames. bool no_stop_waiting_frames_;
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc index 7fa3a95f..0ee071c 100644 --- a/net/quic/core/quic_connection_test.cc +++ b/net/quic/core/quic_connection_test.cc
@@ -999,7 +999,7 @@ const QuicAckFrame InitAckFrame(QuicPacketNumber largest_observed) { QuicAckFrame frame(MakeAckFrame(largest_observed)); if (largest_observed > 0) { - frame.packets.Add(1, largest_observed + 1); + frame.packets.AddRange(1, largest_observed + 1); } return frame; } @@ -1017,12 +1017,12 @@ QuicPacketNumber missing) { QuicAckFrame ack_frame; if (largest_acked > missing) { - ack_frame.packets.Add(1, missing); - ack_frame.packets.Add(missing + 1, largest_acked + 1); + ack_frame.packets.AddRange(1, missing); + ack_frame.packets.AddRange(missing + 1, largest_acked + 1); ack_frame.largest_observed = largest_acked; } if (largest_acked == missing) { - ack_frame.packets.Add(1, missing); + ack_frame.packets.AddRange(1, missing); ack_frame.largest_observed = largest_acked; } return ack_frame; @@ -3151,12 +3151,12 @@ mtu_discovery_packets.end()); QuicPacketNumber max_packet = *max_element(mtu_discovery_packets.begin(), mtu_discovery_packets.end()); - ack.packets.Add(1, min_packet); - ack.packets.Add(max_packet + 1, creator_->packet_number() + 1); + ack.packets.AddRange(1, min_packet); + ack.packets.AddRange(max_packet + 1, creator_->packet_number() + 1); ack.largest_observed = creator_->packet_number(); } else { - ack.packets.Add(1, creator_->packet_number() + 1); + ack.packets.AddRange(1, creator_->packet_number() + 1); ack.largest_observed = creator_->packet_number(); } @@ -3846,6 +3846,64 @@ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); } +TEST_P(QuicConnectionTest, SendDelayedAckDecimationUnlimitedAggregation) { + FLAGS_quic_reloadable_flag_quic_ack_decimation = true; + EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + QuicConfig config; + QuicTagVector connection_options; + connection_options.push_back(kACKD); + // No limit on the number of packets received before sending an ack. + connection_options.push_back(kAKDU); + config.SetConnectionOptionsToSend(connection_options); + connection_.SetFromConfig(config); + + const size_t kMinRttMs = 40; + RttStats* rtt_stats = const_cast<RttStats*>(manager_->GetRttStats()); + rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kMinRttMs), + QuicTime::Delta::Zero(), QuicTime::Zero()); + // The ack time should be based on min_rtt/4, since it's less than the + // default delayed ack time. + QuicTime ack_time = clock_.ApproximateNow() + + QuicTime::Delta::FromMilliseconds(kMinRttMs / 4); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + const uint8_t tag = 0x07; + connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag)); + peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag)); + // Process a packet from the non-crypto stream. + frame1_.stream_id = 3; + + // Process all the initial packets in order so there aren't missing packets. + QuicPacketNumber kFirstDecimatedPacket = 101; + for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) { + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL); + } + EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); + // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used + // instead of ENCRYPTION_NONE. + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting, + ENCRYPTION_INITIAL); + + // Check if delayed ack timer is running for the expected interval. + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); + + // 18 packets will not cause an ack to be sent. 19 will because when + // stop waiting frames are in use, we ack every 20 packets no matter what. + for (int i = 0; i < 18; ++i) { + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting, + ENCRYPTION_INITIAL); + } + // The delayed ack timer should still be set to the expected deadline. + EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); + EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); +} + TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) { EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); QuicConnectionPeer::SetAckMode(&connection_, QuicConnection::ACK_DECIMATION);
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index ee70910..958f5041 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -117,12 +117,6 @@ // If enabled, use refactored stream creation methods. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_refactor_stream_creation, false) -// If true, GFEs generate and validate source address token using the actual -// client IP for proxied session. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_use_client_address_for_stk_in_proxy, - true) - // If true, export a varz mapping QUIC non 0-rtt handshake with corresponding // frontend service. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_account_handshake, false) @@ -137,9 +131,6 @@ // If true, enable QUIC v40. QUIC_FLAG(bool, FLAGS_quic_enable_version_40, false) -// If true, use the more CPU efficient bandwidth sampler datastructure. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_faster_bandwidth_sampler, true) - // In QUIC, QuicSession gets notified when stream frames are acked, discarded or // retransmitted. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_stream_notifier2, false) @@ -206,3 +197,7 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes4, false) + +// Add 4 new ack decimation modes to QUIC that are entirely time based at 1/4 +// or 1/8 RTT. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_ack_decimation, false)
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc index 09dd259..56b3bd0 100644 --- a/net/quic/core/quic_framer.cc +++ b/net/quic/core/quic_framer.cc
@@ -73,31 +73,37 @@ // Stream frame relative shifts and masks for interpreting the stream flags. // StreamID may be 1, 2, 3, or 4 bytes. const uint8_t kQuicStreamIdShift_Pre40 = 2; -const uint8_t kQuicStreamIDLengthMask = 0x03; +const uint8_t kQuicStreamIDLengthMask_Pre40 = 0x03; const uint8_t kQuicStreamIDLengthOffsetShift = 3; +const uint8_t kQuicStreamIDLengthNumBits = 2; // Offset may be 0, 2, 4, or 8 bytes. const uint8_t kQuicStreamOffsetShift_Pre40 = 3; const uint8_t kQuicStreamOffsetMask_Pre40 = 0x07; -const uint8_t kQuicStreamOffsetMask = 0x03; +const uint8_t kQuicStreamOffsetNumBits = 2; const uint8_t kQuicStreamOffsetOffsetShift = 1; // Data length may be 0 or 2 bytes. const uint8_t kQuicStreamDataLengthShift_Pre40 = 1; -const uint8_t kQuicStreamDataLengthMask = 0x01; +const uint8_t kQuicStreamDataLengthMask_Pre40 = 0x01; +const uint8_t kQuicStreamDataLengthNumBits = 1; const uint8_t kQuicStreamDataLengthOffsetShift = 0; // Fin bit may be set or not. const uint8_t kQuicStreamFinShift_Pre40 = 1; -const uint8_t kQuicStreamFinMask = 0x01; +const uint8_t kQuicStreamFinMask_Pre40 = 0x01; +const uint8_t kQuicStreamFinNumBits = 0x01; const uint8_t kQuicStreamFinOffsetShift = 5; // packet number size shift used in AckFrames. -const uint8_t kQuicSequenceNumberLengthShift = 2; +const uint8_t kQuicSequenceNumberLengthNumBits = 2; +const uint8_t kActBlockLengthOffset = 0; +const uint8_t kLargestAckedOffset = 2; // Acks may have only one ack block. -const uint8_t kQuicHasMultipleAckBlocksMask = 0x01; -const uint8_t kQuicHasMultipleAckBlocksShift_Pre40 = 1; +const uint8_t kQuicHasMultipleAckBlocksOffset_Pre40 = 5; +const uint8_t kQuicHasMultipleAckBlocksOffset = 4; +const uint8_t kBooleanNumBits = 1; // Returns the absolute value of the difference between |a| and |b|. QuicPacketNumber Delta(QuicPacketNumber a, QuicPacketNumber b) { @@ -1150,10 +1156,24 @@ return true; } -uint8_t ExtractBits(uint8_t flags, uint8_t num_bits, uint8_t offset) { - return ((flags >> offset) & ~(0xFF << num_bits)); +namespace { +// Create a mask that sets the last |num_bits| to 1 and the rest to 0. +inline uint8_t GetMaskFromNumBits(uint8_t num_bits) { + return (1u << num_bits) - 1; } +// Extract |num_bits| from |flags| offset by |offset|. +uint8_t ExtractBits(uint8_t flags, uint8_t num_bits, uint8_t offset) { + return (flags >> offset) & GetMaskFromNumBits(num_bits); +} + +// Set |num_bits|, offset by |offset| to |val| in |flags|. +void SetBits(uint8_t* flags, uint8_t val, uint8_t num_bits, uint8_t offset) { + DCHECK_LE(val, GetMaskFromNumBits(num_bits)); + *flags |= val << offset; +} +} // namespace + bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, uint8_t frame_type, QuicStreamFrame* frame) { @@ -1166,7 +1186,7 @@ stream_flags &= ~kQuicFrameTypeStreamMask_Pre40; // Read from right to left: StreamID, Offset, Data Length, Fin. - stream_id_length = (stream_flags & kQuicStreamIDLengthMask) + 1; + stream_id_length = (stream_flags & kQuicStreamIDLengthMask_Pre40) + 1; stream_flags >>= kQuicStreamIdShift_Pre40; offset_length = (stream_flags & kQuicStreamOffsetMask_Pre40); @@ -1176,31 +1196,31 @@ } stream_flags >>= kQuicStreamOffsetShift_Pre40; - has_data_length = - (stream_flags & kQuicStreamDataLengthMask) == kQuicStreamDataLengthMask; + has_data_length = (stream_flags & kQuicStreamDataLengthMask_Pre40) == + kQuicStreamDataLengthMask_Pre40; stream_flags >>= kQuicStreamDataLengthShift_Pre40; frame->fin = - (stream_flags & kQuicStreamFinMask) == kQuicStreamFinShift_Pre40; + (stream_flags & kQuicStreamFinMask_Pre40) == kQuicStreamFinShift_Pre40; } else { stream_flags &= ~kQuicFrameTypeStreamMask; - stream_id_length = 1 + ((stream_flags >> kQuicStreamIDLengthOffsetShift) & - kQuicStreamIDLengthMask); + stream_id_length = 1 + ExtractBits(stream_flags, kQuicStreamIDLengthNumBits, + kQuicStreamIDLengthOffsetShift); - offset_length = 1 << ((stream_flags >> kQuicStreamOffsetOffsetShift) & - kQuicStreamOffsetMask); + offset_length = 1 << ExtractBits(stream_flags, kQuicStreamOffsetNumBits, + kQuicStreamOffsetOffsetShift); if (offset_length == 1) { offset_length = 0; } - has_data_length = stream_flags & (kQuicStreamDataLengthMask - << kQuicStreamDataLengthOffsetShift); + has_data_length = ExtractBits(stream_flags, kQuicStreamDataLengthNumBits, + kQuicStreamDataLengthOffsetShift); - frame->fin = ((stream_flags >> kQuicStreamFinOffsetShift) & - kQuicStreamFinMask) == kQuicStreamFinMask; + frame->fin = ExtractBits(stream_flags, kQuicStreamFinNumBits, + kQuicStreamFinOffsetShift); } uint16_t data_len = 0; @@ -1254,17 +1274,16 @@ QuicAckFrame* ack_frame) { // Determine the two lengths from the frame type: largest acked length, // ack block length. - uint8_t offset = 0u; const QuicPacketNumberLength ack_block_length = - ReadSequenceNumberLength(ExtractBits(frame_type, 2, offset)); - offset += kQuicSequenceNumberLengthShift; + ReadSequenceNumberLength(ExtractBits( + frame_type, kQuicSequenceNumberLengthNumBits, kActBlockLengthOffset)); const QuicPacketNumberLength largest_acked_length = - ReadSequenceNumberLength(ExtractBits(frame_type, 2, offset)); - offset += kQuicSequenceNumberLengthShift; - if (quic_version_ < QUIC_VERSION_40) { - offset += kQuicHasMultipleAckBlocksShift_Pre40; - } - bool has_ack_blocks = ExtractBits(frame_type, 1, offset) != 0; + ReadSequenceNumberLength(ExtractBits( + frame_type, kQuicSequenceNumberLengthNumBits, kLargestAckedOffset)); + bool has_ack_blocks = ExtractBits(frame_type, kBooleanNumBits, + quic_version_ < QUIC_VERSION_40 + ? kQuicHasMultipleAckBlocksOffset_Pre40 + : kQuicHasMultipleAckBlocksOffset); if (!reader->ReadBytesToUInt64(largest_acked_length, &ack_frame->largest_observed)) { @@ -1300,7 +1319,7 @@ } QuicPacketNumber first_received = ack_frame->largest_observed + 1 - first_block_length; - ack_frame->packets.Add(first_received, ack_frame->largest_observed + 1); + ack_frame->packets.AddRange(first_received, ack_frame->largest_observed + 1); if (num_ack_blocks > 0) { for (size_t i = 0; i < num_ack_blocks; ++i) { @@ -1316,8 +1335,8 @@ } first_received -= (gap + current_block_length); if (current_block_length > 0) { - ack_frame->packets.Add(first_received, - first_received + current_block_length); + ack_frame->packets.AddRange(first_received, + first_received + current_block_length); } } } @@ -1801,11 +1820,12 @@ } if (quic_version_ < QUIC_VERSION_40) { // Fin bit. - type_byte |= frame.stream_frame->fin ? kQuicStreamFinMask : 0; + type_byte |= frame.stream_frame->fin ? kQuicStreamFinMask_Pre40 : 0; // Data Length bit. type_byte <<= kQuicStreamDataLengthShift_Pre40; - type_byte |= no_stream_frame_length ? 0 : kQuicStreamDataLengthMask; + type_byte |= + no_stream_frame_length ? 0 : kQuicStreamDataLengthMask_Pre40; // Offset 3 bits. type_byte <<= kQuicStreamOffsetShift_Pre40; @@ -1822,12 +1842,12 @@ kQuicFrameTypeStreamMask_Pre40; // Set Stream Frame Type to 1. } else { // Fin bit. - type_byte |= ((frame.stream_frame->fin ? kQuicStreamFinMask : 0) - << kQuicStreamFinOffsetShift); + SetBits(&type_byte, frame.stream_frame->fin ? 1 : 0, + kQuicStreamFinNumBits, kQuicStreamFinOffsetShift); // Data Length bit. - type_byte |= ((no_stream_frame_length ? 0 : kQuicStreamDataLengthMask) - << kQuicStreamDataLengthOffsetShift); + SetBits(&type_byte, no_stream_frame_length ? 0 : 1, + kQuicStreamDataLengthNumBits, kQuicStreamDataLengthOffsetShift); // Offset 2 bits. uint8_t offset_len_encode = 3; @@ -1848,11 +1868,12 @@ default: QUIC_BUG << "Invalid offset_length."; } - type_byte |= (offset_len_encode) << kQuicStreamOffsetOffsetShift; + SetBits(&type_byte, offset_len_encode, kQuicStreamOffsetNumBits, + kQuicStreamOffsetOffsetShift); // stream id 2 bits. - type_byte |= ((GetStreamIdSize(frame.stream_frame->stream_id) - 1) - << kQuicStreamIDLengthOffsetShift); + SetBits(&type_byte, GetStreamIdSize(frame.stream_frame->stream_id) - 1, + kQuicStreamIDLengthNumBits, kQuicStreamIDLengthOffsetShift); type_byte |= kQuicFrameTypeStreamMask; // Set Stream Frame Type to 1. } break; @@ -1985,18 +2006,17 @@ // Write out the type byte by setting the low order bits and doing shifts // to make room for the next bit flags to be set. // Whether there are multiple ack blocks. - uint8_t type_byte = - new_ack_info.num_ack_blocks == 0 ? 0 : kQuicHasMultipleAckBlocksMask; - if (quic_version_ < QUIC_VERSION_40) { - type_byte <<= kQuicHasMultipleAckBlocksShift_Pre40; - } - // Largest acked length. - type_byte <<= kQuicSequenceNumberLengthShift; - type_byte |= GetPacketNumberFlags(largest_acked_length); + uint8_t type_byte = 0; + SetBits(&type_byte, new_ack_info.num_ack_blocks == 0 ? 0 : 1, kBooleanNumBits, + quic_version_ < QUIC_VERSION_40 + ? kQuicHasMultipleAckBlocksOffset_Pre40 + : kQuicHasMultipleAckBlocksOffset); - // Ack block length. - type_byte <<= kQuicSequenceNumberLengthShift; - type_byte |= GetPacketNumberFlags(ack_block_length); + SetBits(&type_byte, GetPacketNumberFlags(largest_acked_length), + kQuicSequenceNumberLengthNumBits, kLargestAckedOffset); + + SetBits(&type_byte, GetPacketNumberFlags(ack_block_length), + kQuicSequenceNumberLengthNumBits, kActBlockLengthOffset); if (quic_version_ < QUIC_VERSION_40) { type_byte |= kQuicFrameTypeAckMask_Pre40;
diff --git a/net/quic/core/quic_framer_test.cc b/net/quic/core/quic_framer_test.cc index 8486999..976d1917 100644 --- a/net/quic/core/quic_framer_test.cc +++ b/net/quic/core/quic_framer_test.cc
@@ -3741,7 +3741,7 @@ QuicAckFrame ack_frame; ack_frame.largest_observed = kSmallLargestObserved; ack_frame.ack_delay_time = QuicTime::Delta::Zero(); - ack_frame.packets.Add(1, kSmallLargestObserved + 1); + ack_frame.packets.AddRange(1, kSmallLargestObserved + 1); QuicFrames frames = {QuicFrame(&ack_frame)}; @@ -3834,10 +3834,11 @@ QuicAckFrame ack_frame; ack_frame.largest_observed = kSmallLargestObserved; ack_frame.ack_delay_time = QuicTime::Delta::Zero(); - ack_frame.packets.Add(1, 5); - ack_frame.packets.Add(10, 500); - ack_frame.packets.Add(900, kSmallMissingPacket); - ack_frame.packets.Add(kSmallMissingPacket + 1, kSmallLargestObserved + 1); + ack_frame.packets.AddRange(1, 5); + ack_frame.packets.AddRange(10, 500); + ack_frame.packets.AddRange(900, kSmallMissingPacket); + ack_frame.packets.AddRange(kSmallMissingPacket + 1, + kSmallLargestObserved + 1); QuicFrames frames = {QuicFrame(&ack_frame)}; @@ -3989,7 +3990,7 @@ for (size_t i = 2; i < 2 * 300; i += 2) { ack_frame.packets.Add(i); } - ack_frame.packets.Add(600, kSmallLargestObserved + 1); + ack_frame.packets.AddRange(600, kSmallLargestObserved + 1); QuicFrames frames = {QuicFrame(&ack_frame)}; @@ -5074,7 +5075,7 @@ QuicAckFrame ack_frame; ack_frame.largest_observed = 201; - ack_frame.packets.Add(1, ack_frame.largest_observed); + ack_frame.packets.AddRange(1, ack_frame.largest_observed); // Create a packet with just the ack. QuicFrames frames = {QuicFrame(&ack_frame)};
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc index 139c023..3aece47 100644 --- a/net/quic/core/quic_sent_packet_manager.cc +++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -309,6 +309,7 @@ break; } if (skip_unackable_packets_early && it->is_unackable) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_handle_acks); continue; } if (!ack_frame.packets.Contains(packet_number)) {
diff --git a/net/quic/core/quic_sent_packet_manager_test.cc b/net/quic/core/quic_sent_packet_manager_test.cc index 031b7e8..4de9065 100644 --- a/net/quic/core/quic_sent_packet_manager_test.cc +++ b/net/quic/core/quic_sent_packet_manager_test.cc
@@ -257,7 +257,7 @@ const QuicAckFrame InitAckFrame(QuicPacketNumber largest_observed) { QuicAckFrame frame(MakeAckFrame(largest_observed)); if (largest_observed > 0) { - frame.packets.Add(1, largest_observed + 1); + frame.packets.AddRange(1, largest_observed + 1); } return frame; } @@ -269,10 +269,10 @@ QuicPacketNumber range2_end) { QuicAckFrame ack_frame; if (range1_start < range1_end) { - ack_frame.packets.Add(range1_start, range1_end); + ack_frame.packets.AddRange(range1_start, range1_end); } if (range2_start <= range2_end) { - ack_frame.packets.Add(range2_start, range2_end + 1); + ack_frame.packets.AddRange(range2_start, range2_end + 1); } ack_frame.largest_observed = range2_end; return ack_frame; @@ -766,8 +766,8 @@ QuicPacketNumber acked[] = {3, 4, 5, 8, 9}; ExpectAcksAndLosses(true, acked, arraysize(acked), nullptr, 0); QuicAckFrame ack_frame; - ack_frame.packets.Add(3, 6); - ack_frame.packets.Add(8, 10); + ack_frame.packets.AddRange(3, 6); + ack_frame.packets.AddRange(8, 10); ack_frame.largest_observed = 9; manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
diff --git a/net/quic/core/quic_client_session_base.cc b/net/quic/core/quic_spdy_client_session_base.cc similarity index 79% rename from net/quic/core/quic_client_session_base.cc rename to net/quic/core/quic_spdy_client_session_base.cc index b13496d..a1fd538 100644 --- a/net/quic/core/quic_client_session_base.cc +++ b/net/quic/core/quic_spdy_client_session_base.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 "net/quic/core/quic_client_session_base.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/quic/core/quic_client_promised_info.h" #include "net/quic/core/spdy_utils.h" @@ -13,7 +13,7 @@ namespace net { -QuicClientSessionBase::QuicClientSessionBase( +QuicSpdyClientSessionBase::QuicSpdyClientSessionBase( QuicConnection* connection, QuicClientPushPromiseIndex* push_promise_index, const QuicConfig& config) @@ -21,7 +21,7 @@ push_promise_index_(push_promise_index), largest_promised_stream_id_(kInvalidStreamId) {} -QuicClientSessionBase::~QuicClientSessionBase() { +QuicSpdyClientSessionBase::~QuicSpdyClientSessionBase() { // all promised streams for this session for (auto& it : promised_by_id_) { QUIC_DVLOG(1) << "erase stream " << it.first << " url " << it.second->url(); @@ -30,15 +30,16 @@ delete connection(); } -void QuicClientSessionBase::OnConfigNegotiated() { +void QuicSpdyClientSessionBase::OnConfigNegotiated() { QuicSpdySession::OnConfigNegotiated(); } -void QuicClientSessionBase::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { +void QuicSpdyClientSessionBase::OnCryptoHandshakeEvent( + CryptoHandshakeEvent event) { QuicSpdySession::OnCryptoHandshakeEvent(event); } -void QuicClientSessionBase::OnInitialHeadersComplete( +void QuicSpdyClientSessionBase::OnInitialHeadersComplete( QuicStreamId stream_id, const SpdyHeaderBlock& response_headers) { // Note that the strong ordering of the headers stream means that @@ -53,7 +54,7 @@ promised->OnResponseHeaders(response_headers); } -void QuicClientSessionBase::OnPromiseHeaderList( +void QuicSpdyClientSessionBase::OnPromiseHeaderList( QuicStreamId stream_id, QuicStreamId promised_stream_id, size_t frame_len, @@ -77,9 +78,9 @@ stream->OnPromiseHeaderList(promised_stream_id, frame_len, header_list); } -bool QuicClientSessionBase::HandlePromised(QuicStreamId /* associated_id */, - QuicStreamId promised_id, - const SpdyHeaderBlock& headers) { +bool QuicSpdyClientSessionBase::HandlePromised(QuicStreamId /* associated_id */, + QuicStreamId promised_id, + const SpdyHeaderBlock& headers) { // Due to pathalogical packet re-ordering, it is possible that // frames for the promised stream have already arrived, and the // promised stream could be active or closed. @@ -126,7 +127,7 @@ return true; } -QuicClientPromisedInfo* QuicClientSessionBase::GetPromisedByUrl( +QuicClientPromisedInfo* QuicSpdyClientSessionBase::GetPromisedByUrl( const string& url) { QuicPromisedByUrlMap::iterator it = push_promise_index_->promised_by_url()->find(url); @@ -136,7 +137,7 @@ return nullptr; } -QuicClientPromisedInfo* QuicClientSessionBase::GetPromisedById( +QuicClientPromisedInfo* QuicSpdyClientSessionBase::GetPromisedById( const QuicStreamId id) { QuicPromisedByIdMap::iterator it = promised_by_id_.find(id); if (it != promised_by_id_.end()) { @@ -145,7 +146,7 @@ return nullptr; } -QuicSpdyStream* QuicClientSessionBase::GetPromisedStream( +QuicSpdyStream* QuicSpdyClientSessionBase::GetPromisedStream( const QuicStreamId id) { DynamicStreamMap::iterator it = dynamic_streams().find(id); if (it != dynamic_streams().end()) { @@ -154,7 +155,8 @@ return nullptr; } -void QuicClientSessionBase::DeletePromised(QuicClientPromisedInfo* promised) { +void QuicSpdyClientSessionBase::DeletePromised( + QuicClientPromisedInfo* promised) { push_promise_index_->promised_by_url()->erase(promised->url()); // Since promised_by_id_ contains the unique_ptr, this will destroy // promised. @@ -162,23 +164,24 @@ headers_stream()->MaybeReleaseSequencerBuffer(); } -void QuicClientSessionBase::OnPushStreamTimedOut(QuicStreamId stream_id) {} +void QuicSpdyClientSessionBase::OnPushStreamTimedOut(QuicStreamId stream_id) {} -void QuicClientSessionBase::ResetPromised(QuicStreamId id, - QuicRstStreamErrorCode error_code) { +void QuicSpdyClientSessionBase::ResetPromised( + QuicStreamId id, + QuicRstStreamErrorCode error_code) { SendRstStream(id, error_code, 0); if (!IsOpenStream(id)) { MaybeIncreaseLargestPeerStreamId(id); } } -void QuicClientSessionBase::CloseStreamInner(QuicStreamId stream_id, - bool locally_reset) { +void QuicSpdyClientSessionBase::CloseStreamInner(QuicStreamId stream_id, + bool locally_reset) { QuicSpdySession::CloseStreamInner(stream_id, locally_reset); headers_stream()->MaybeReleaseSequencerBuffer(); } -bool QuicClientSessionBase::ShouldReleaseHeadersStreamSequencerBuffer() { +bool QuicSpdyClientSessionBase::ShouldReleaseHeadersStreamSequencerBuffer() { return num_active_requests() == 0 && promised_by_id_.empty(); }
diff --git a/net/quic/core/quic_client_session_base.h b/net/quic/core/quic_spdy_client_session_base.h similarity index 90% rename from net/quic/core/quic_client_session_base.h rename to net/quic/core/quic_spdy_client_session_base.h index 8e6c1a6d..696be5e 100644 --- a/net/quic/core/quic_client_session_base.h +++ b/net/quic/core/quic_spdy_client_session_base.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 NET_QUIC_CORE_QUIC_CLIENT_SESSION_BASE_H_ -#define NET_QUIC_CORE_QUIC_CLIENT_SESSION_BASE_H_ +#ifndef NET_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_BASE_H_ +#define NET_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_BASE_H_ #include <string> @@ -33,17 +33,17 @@ const int64_t kPushPromiseTimeoutSecs = 60; // Base class for all client-specific QuicSession subclasses. -class QUIC_EXPORT_PRIVATE QuicClientSessionBase +class QUIC_EXPORT_PRIVATE QuicSpdyClientSessionBase : public QuicSpdySession, public QuicCryptoClientStream::ProofHandler { public: // Takes ownership of |connection|. Caller retains ownership of // |promised_by_url|. - QuicClientSessionBase(QuicConnection* connection, - QuicClientPushPromiseIndex* push_promise_index, - const QuicConfig& config); + QuicSpdyClientSessionBase(QuicConnection* connection, + QuicClientPushPromiseIndex* push_promise_index, + const QuicConfig& config); - ~QuicClientSessionBase() override; + ~QuicSpdyClientSessionBase() override; void OnConfigNegotiated() override; @@ -131,9 +131,9 @@ QuicPromisedByIdMap promised_by_id_; QuicStreamId largest_promised_stream_id_; - DISALLOW_COPY_AND_ASSIGN(QuicClientSessionBase); + DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientSessionBase); }; } // namespace net -#endif // NET_QUIC_CORE_QUIC_CLIENT_SESSION_BASE_H_ +#endif // NET_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_BASE_H_
diff --git a/net/quic/platform/api/quic_text_utils_test.cc b/net/quic/platform/api/quic_text_utils_test.cc index 8bbbbad..23e3c46 100644 --- a/net/quic/platform/api/quic_text_utils_test.cc +++ b/net/quic/platform/api/quic_text_utils_test.cc
@@ -13,9 +13,9 @@ namespace net { namespace test { -class QuicTextUtilsText : public QuicTest {}; +class QuicTextUtilsTest : public QuicTest {}; -TEST_F(QuicTextUtilsText, StartsWith) { +TEST_F(QuicTextUtilsTest, StartsWith) { EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", "hello")); EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", "hello world")); EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", "")); @@ -24,7 +24,7 @@ EXPECT_FALSE(QuicTextUtils::StartsWith("hello world", "bar")); } -TEST_F(QuicTextUtilsText, EndsWithIgnoreCase) { +TEST_F(QuicTextUtilsTest, EndsWithIgnoreCase) { EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "world")); EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "hello world")); EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "")); @@ -32,7 +32,7 @@ EXPECT_FALSE(QuicTextUtils::EndsWithIgnoreCase("hello world", "hello")); } -TEST_F(QuicTextUtilsText, ToLower) { +TEST_F(QuicTextUtilsTest, ToLower) { EXPECT_EQ("lower", QuicTextUtils::ToLower("LOWER")); EXPECT_EQ("lower", QuicTextUtils::ToLower("lower")); EXPECT_EQ("lower", QuicTextUtils::ToLower("lOwEr")); @@ -40,7 +40,7 @@ EXPECT_EQ("", QuicTextUtils::ToLower("")); } -TEST_F(QuicTextUtilsText, RemoveLeadingAndTrailingWhitespace) { +TEST_F(QuicTextUtilsTest, RemoveLeadingAndTrailingWhitespace) { string input; for (auto* input : {"text", " text", " text", "text ", "text ", " text ", @@ -51,7 +51,7 @@ } } -TEST_F(QuicTextUtilsText, StringToNumbers) { +TEST_F(QuicTextUtilsTest, StringToNumbers) { const string kMaxInt32Plus1 = "2147483648"; const string kMinInt32Minus1 = "-2147483649"; const string kMaxUint32Plus1 = "4294967296"; @@ -124,25 +124,25 @@ } } -TEST_F(QuicTextUtilsText, Uint64ToString) { +TEST_F(QuicTextUtilsTest, Uint64ToString) { EXPECT_EQ("123", QuicTextUtils::Uint64ToString(123)); EXPECT_EQ("1234", QuicTextUtils::Uint64ToString(1234)); } -TEST_F(QuicTextUtilsText, HexEncode) { +TEST_F(QuicTextUtilsTest, HexEncode) { EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello", 5)); EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello World", 5)); EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello")); EXPECT_EQ("0102779cfa", QuicTextUtils::HexEncode("\x01\x02\x77\x9c\xfa")); } -TEST_F(QuicTextUtilsText, HexDecode) { +TEST_F(QuicTextUtilsTest, HexDecode) { EXPECT_EQ("Hello", QuicTextUtils::HexDecode("48656c6c6f")); EXPECT_EQ("", QuicTextUtils::HexDecode("")); EXPECT_EQ("\x01\x02\x77\x9c\xfa", QuicTextUtils::HexDecode("0102779cfa")); } -TEST_F(QuicTextUtilsText, HexDump) { +TEST_F(QuicTextUtilsTest, HexDump) { // Verify output of the HexDump method is as expected. char packet[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21, @@ -161,9 +161,16 @@ "0x0030: 6f20 7370 616e 206d 756c 7469 706c 6520 o.span.multiple.\n" "0x0040: 6c69 6e65 7320 6f66 206f 7574 7075 742e lines.of.output.\n" "0x0050: 0102 03 ...\n"); + // Verify that 0x21 and 0x7e are printable, 0x20 and 0x7f are not. + EXPECT_EQ("0x0000: 2021 7e7f .!~.\n", + QuicTextUtils::HexDump(QuicTextUtils::HexDecode("20217e7f"))); + // Verify that values above numeric_limits<unsigned char>::max() are formatted + // properly on platforms where char is unsigned. + EXPECT_EQ("0x0000: 90aa ff ...\n", + QuicTextUtils::HexDump(QuicTextUtils::HexDecode("90aaff"))); } -TEST_F(QuicTextUtilsText, Base64Encode) { +TEST_F(QuicTextUtilsTest, Base64Encode) { string output; string input = "Hello"; QuicTextUtils::Base64Encode(reinterpret_cast<const uint8_t*>(input.data()), @@ -181,7 +188,7 @@ output); } -TEST_F(QuicTextUtilsText, ContainsUpperCase) { +TEST_F(QuicTextUtilsTest, ContainsUpperCase) { EXPECT_FALSE(QuicTextUtils::ContainsUpperCase("abc")); EXPECT_FALSE(QuicTextUtils::ContainsUpperCase("")); EXPECT_FALSE(QuicTextUtils::ContainsUpperCase("123")); @@ -189,7 +196,7 @@ EXPECT_TRUE(QuicTextUtils::ContainsUpperCase("aBc")); } -TEST_F(QuicTextUtilsText, Split) { +TEST_F(QuicTextUtilsTest, Split) { EXPECT_EQ(std::vector<QuicStringPiece>({"a", "b", "c"}), QuicTextUtils::Split("a,b,c", ',')); EXPECT_EQ(std::vector<QuicStringPiece>({"a", "b", "c"}),
diff --git a/net/quic/test_tools/mock_crypto_client_stream.cc b/net/quic/test_tools/mock_crypto_client_stream.cc index ba12953..397fc00f 100644 --- a/net/quic/test_tools/mock_crypto_client_stream.cc +++ b/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -8,7 +8,7 @@ #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_client_session_base.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/quic/test_tools/quic_config_peer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,7 +18,7 @@ MockCryptoClientStream::MockCryptoClientStream( const QuicServerId& server_id, - QuicClientSessionBase* session, + QuicSpdyClientSessionBase* session, ProofVerifyContext* verify_context, const QuicConfig& config, QuicCryptoClientConfig* crypto_config, @@ -66,7 +66,7 @@ crypto_negotiated_params_->key_exchange = kC255; crypto_negotiated_params_->aead = kAESG; if (proof_verify_details_) { - reinterpret_cast<QuicClientSessionBase*>(session()) + reinterpret_cast<QuicSpdyClientSessionBase*>(session()) ->OnProofVerifyDetailsAvailable(*proof_verify_details_); } session()->connection()->SetDecrypter( @@ -85,7 +85,7 @@ crypto_negotiated_params_->key_exchange = kC255; crypto_negotiated_params_->aead = kAESG; if (proof_verify_details_) { - reinterpret_cast<QuicClientSessionBase*>(session()) + reinterpret_cast<QuicSpdyClientSessionBase*>(session()) ->OnProofVerifyDetailsAvailable(*proof_verify_details_); } SetConfigNegotiated();
diff --git a/net/quic/test_tools/mock_crypto_client_stream.h b/net/quic/test_tools/mock_crypto_client_stream.h index 30e1f9b..b31c6e6 100644 --- a/net/quic/test_tools/mock_crypto_client_stream.h +++ b/net/quic/test_tools/mock_crypto_client_stream.h
@@ -11,10 +11,10 @@ #include "net/quic/chromium/crypto/proof_verifier_chromium.h" #include "net/quic/core/crypto/crypto_handshake.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_client_session_base.h" #include "net/quic/core/quic_crypto_client_stream.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/quic_session.h" +#include "net/quic/core/quic_spdy_client_session_base.h" namespace net { @@ -47,7 +47,7 @@ MockCryptoClientStream( const QuicServerId& server_id, - QuicClientSessionBase* session, + QuicSpdyClientSessionBase* session, ProofVerifyContext* verify_context, const QuicConfig& config, QuicCryptoClientConfig* crypto_config,
diff --git a/net/quic/test_tools/mock_quic_client_promised_info.cc b/net/quic/test_tools/mock_quic_client_promised_info.cc index 793ed3fd..7518ac2 100644 --- a/net/quic/test_tools/mock_quic_client_promised_info.cc +++ b/net/quic/test_tools/mock_quic_client_promised_info.cc
@@ -10,7 +10,7 @@ namespace test { MockQuicClientPromisedInfo::MockQuicClientPromisedInfo( - QuicClientSessionBase* session, + QuicSpdyClientSessionBase* session, QuicStreamId id, string url) : QuicClientPromisedInfo(session, id, url) {}
diff --git a/net/quic/test_tools/mock_quic_client_promised_info.h b/net/quic/test_tools/mock_quic_client_promised_info.h index 4137b56..ab10cb5 100644 --- a/net/quic/test_tools/mock_quic_client_promised_info.h +++ b/net/quic/test_tools/mock_quic_client_promised_info.h
@@ -17,7 +17,7 @@ class MockQuicClientPromisedInfo : public QuicClientPromisedInfo { public: - MockQuicClientPromisedInfo(QuicClientSessionBase* session, + MockQuicClientPromisedInfo(QuicSpdyClientSessionBase* session, QuicStreamId id, std::string url); ~MockQuicClientPromisedInfo() override;
diff --git a/net/quic/test_tools/mock_quic_spdy_client_stream.cc b/net/quic/test_tools/mock_quic_spdy_client_stream.cc index 6da6fd0..9eb1451 100644 --- a/net/quic/test_tools/mock_quic_spdy_client_stream.cc +++ b/net/quic/test_tools/mock_quic_spdy_client_stream.cc
@@ -7,8 +7,9 @@ namespace net { namespace test { -MockQuicSpdyClientStream::MockQuicSpdyClientStream(QuicStreamId id, - QuicClientSession* session) +MockQuicSpdyClientStream::MockQuicSpdyClientStream( + QuicStreamId id, + QuicSpdyClientSession* session) : QuicSpdyClientStream(id, session) {} MockQuicSpdyClientStream::~MockQuicSpdyClientStream() {}
diff --git a/net/quic/test_tools/mock_quic_spdy_client_stream.h b/net/quic/test_tools/mock_quic_spdy_client_stream.h index e4ca6007..dcaeb7ab9 100644 --- a/net/quic/test_tools/mock_quic_spdy_client_stream.h +++ b/net/quic/test_tools/mock_quic_spdy_client_stream.h
@@ -16,7 +16,7 @@ class MockQuicSpdyClientStream : public QuicSpdyClientStream { public: - MockQuicSpdyClientStream(QuicStreamId id, QuicClientSession* session); + MockQuicSpdyClientStream(QuicStreamId id, QuicSpdyClientSession* session); ~MockQuicSpdyClientStream() override; MOCK_METHOD1(OnStreamFrame, void(const QuicStreamFrame& frame));
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index ab117b81..9f22b2f 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc
@@ -484,7 +484,7 @@ const QuicConfig& config, const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config) - : QuicClientSessionBase(connection, &push_promise_index_, config) { + : QuicSpdyClientSessionBase(connection, &push_promise_index_, config) { crypto_stream_.reset(new QuicCryptoClientStream( server_id, this, crypto_test_utils::ProofVerifyContextForTesting(), crypto_config, this));
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index 5cb218d..1f721c8 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h
@@ -694,7 +694,7 @@ QuicSpdyStream* rendezvous_stream_; }; -class TestQuicSpdyClientSession : public QuicClientSessionBase { +class TestQuicSpdyClientSession : public QuicSpdyClientSessionBase { public: TestQuicSpdyClientSession(QuicConnection* connection, const QuicConfig& config, @@ -704,7 +704,7 @@ bool IsAuthorized(const std::string& authority) override; - // QuicClientSessionBase + // QuicSpdyClientSessionBase MOCK_METHOD1(OnProofValid, void(const QuicCryptoClientConfig::CachedState& cached)); MOCK_METHOD1(OnProofVerifyDetailsAvailable,
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index c9ef6ab..9409dae 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -21,12 +21,12 @@ #include "net/base/ip_endpoint.h" #include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" #include "net/quic/core/crypto/null_encrypter.h" -#include "net/quic/core/quic_client_session_base.h" #include "net/quic/core/quic_framer.h" #include "net/quic/core/quic_packet_creator.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/quic_session.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" @@ -263,7 +263,7 @@ ~ClientDelegate() override {} void OnCanWrite() override { EpollEvent event(EPOLLOUT); - client_->OnEvent(client_->GetLatestFD(), &event); + client_->epoll_network_helper()->OnEvent(client_->GetLatestFD(), &event); } private: @@ -421,9 +421,9 @@ if (client_writer_ != nullptr) { client_writer_->Initialize( QuicConnectionPeer::GetHelper( - client_->client()->session()->connection()), + client_->client()->client_session()->connection()), QuicConnectionPeer::GetAlarmFactory( - client_->client()->session()->connection()), + client_->client()->client_session()->connection()), new ClientDelegate(client_->client())); } initialized_ = true; @@ -521,7 +521,7 @@ // per test. void VerifyCleanConnection(bool had_packet_loss) { QuicConnectionStats client_stats = - client_->client()->session()->connection()->GetStats(); + client_->client()->client_session()->connection()->GetStats(); // TODO(ianswett): Determine why this becomes even more flaky with BBR // enabled. b/62141144 if (!had_packet_loss && !FLAGS_quic_reloadable_flag_quic_default_to_bbr) { @@ -537,7 +537,7 @@ const int num_expected_stateless_rejects = (BothSidesSupportStatelessRejects() && - client_->client()->session()->GetNumSentClientHellos() > 0) + client_->client()->client_session()->GetNumSentClientHellos() > 0) ? 1 : 0; EXPECT_EQ(num_expected_stateless_rejects, @@ -579,12 +579,12 @@ QuicStreamId GetNthClientInitiatedId(int n) { return QuicSpdySessionPeer::GetNthClientInitiatedStreamId( - *client_->client()->session(), n); + *client_->client()->client_session(), n); } QuicStreamId GetNthServerInitiatedId(int n) { return QuicSpdySessionPeer::GetNthServerInitiatedStreamId( - *client_->client()->session(), n); + *client_->client()->client_session(), n); } bool initialized_; @@ -616,8 +616,8 @@ TEST_P(EndToEndTest, HandshakeSuccessful) { ASSERT_TRUE(Initialize()); EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - QuicCryptoStream* crypto_stream = - QuicSessionPeer::GetMutableCryptoStream(client_->client()->session()); + QuicCryptoStream* crypto_stream = QuicSessionPeer::GetMutableCryptoStream( + client_->client()->client_session()); QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(crypto_stream); EXPECT_NE(FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer, QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); @@ -921,7 +921,7 @@ const int expected_num_hellos_latest_session = BothSidesSupportStatelessRejects() ? 1 : 2; EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); + client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -933,7 +933,7 @@ EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(headers, body)); - EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos()); + EXPECT_EQ(1, client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -953,7 +953,7 @@ // torn down after the reject. The number of hellos sent on the // latest session is 1. EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); + client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); VerifyCleanConnection(false); @@ -973,7 +973,7 @@ const int expected_num_hellos_latest_session = BothSidesSupportStatelessRejects() ? 1 : 2; EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); + client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -984,7 +984,7 @@ ASSERT_TRUE(client_->client()->connected()); EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos()); + EXPECT_EQ(1, client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -1003,7 +1003,7 @@ // torn down after the reject. The number of hellos sent on the // latest session is 1. EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); + client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); VerifyCleanConnection(false); @@ -1031,7 +1031,7 @@ const int expected_num_hellos_latest_session = BothSidesSupportStatelessRejects() ? 1 : 2; EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); + client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -1043,7 +1043,7 @@ EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(headers, body)); - EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos()); + EXPECT_EQ(1, client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); client_->Disconnect(); @@ -1063,7 +1063,7 @@ // torn down after the reject. The number of hellos sent on the // latest session is 1. EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->session()->GetNumSentClientHellos()); + client_->client()->client_session()->GetNumSentClientHellos()); EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); VerifyCleanConnection(false); @@ -1142,7 +1142,7 @@ const uint64_t flow_control_window = server_config_.GetInitialStreamFlowControlWindowToSend(); QuicSpdyClientStream* stream = client_->GetOrCreateStream(); - QuicSession* session = client_->client()->session(); + QuicSession* session = client_->client()->client_session(); QuicFlowControllerPeer::SetSendWindowOffset(stream->flow_controller(), 0); QuicFlowControllerPeer::SetSendWindowOffset(session->flow_controller(), 0); EXPECT_TRUE(stream->flow_controller()->IsBlocked()); @@ -1181,7 +1181,7 @@ // Force the client to write with a stream ID belonging to a nonexistent // server-side stream. - QuicSpdySession* session = client_->client()->session(); + QuicSpdySession* session = client_->client()->client_session(); QuicSessionPeer::SetNextOutgoingStreamId(session, GetNthServerInitiatedId(0)); client_->SendCustomSynchronousRequest(headers, body); @@ -1189,7 +1189,7 @@ EXPECT_EQ(QUIC_INVALID_STREAM_ID, client_->connection_error()); } -// Test that if the the server will close the connection if the client attempts +// Test that if the server will close the connection if the client attempts // to send a request with overly large headers. TEST_P(EndToEndTest, LargeHeaders) { ASSERT_TRUE(Initialize()); @@ -1274,8 +1274,8 @@ // Make the client misbehave after negotiation. const int kServerMaxStreams = kMaxStreamsMinimumIncrement + 1; - QuicSessionPeer::SetMaxOpenOutgoingStreams(client_->client()->session(), - kServerMaxStreams + 1); + QuicSessionPeer::SetMaxOpenOutgoingStreams( + client_->client()->client_session(), kServerMaxStreams + 1); SpdyHeaderBlock headers; headers[":method"] = "POST"; @@ -1309,7 +1309,7 @@ // The client has received the server's limit and vice versa. EXPECT_EQ(kServerMaxIncomingDynamicStreams, - client_->client()->session()->max_open_outgoing_streams()); + client_->client()->client_session()->max_open_outgoing_streams()); server_thread_->Pause(); QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server_thread_->server()); @@ -1372,7 +1372,7 @@ QuicServerPeer::GetDispatcher(server_thread_->server()); ASSERT_EQ(1u, dispatcher->session_map().size()); const QuicSentPacketManager& client_sent_packet_manager = - client_->client()->session()->connection()->sent_packet_manager(); + client_->client()->client_session()->connection()->sent_packet_manager(); const QuicSentPacketManager* server_sent_packet_manager = GetSentPacketManagerFromFirstServerSession(); @@ -1400,7 +1400,7 @@ ASSERT_EQ(1u, dispatcher->session_map().size()); QuicSession* session = dispatcher->session_map().begin()->second.get(); const QuicSentPacketManager& client_sent_packet_manager = - client_->client()->session()->connection()->sent_packet_manager(); + client_->client()->client_session()->connection()->sent_packet_manager(); // Now that acks have been exchanged, the RTT estimate has decreased on the // server and is not infinite on the client. @@ -1430,7 +1430,7 @@ ASSERT_EQ(1u, dispatcher->session_map().size()); QuicSession* session = dispatcher->session_map().begin()->second.get(); const QuicSentPacketManager& client_sent_packet_manager = - client_->client()->session()->connection()->sent_packet_manager(); + client_->client()->client_session()->connection()->sent_packet_manager(); const QuicSentPacketManager& server_sent_packet_manager = session->connection()->sent_packet_manager(); @@ -1455,7 +1455,7 @@ EXPECT_EQ("200", client_->response_headers()->find(":status")->second); QuicPacketHeader* header = QuicConnectionPeer::GetLastHeader( - client_->client()->session()->connection()); + client_->client()->client_session()->connection()); EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID, header->public_header.connection_id_length); } @@ -1467,7 +1467,7 @@ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); EXPECT_EQ("200", client_->response_headers()->find(":status")->second); QuicPacketHeader* header = QuicConnectionPeer::GetLastHeader( - client_->client()->session()->connection()); + client_->client()->client_session()->connection()); EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, header->public_header.connection_id_length); } @@ -1480,7 +1480,7 @@ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); EXPECT_EQ("200", client_->response_headers()->find(":status")->second); QuicPacketHeader* header = QuicConnectionPeer::GetLastHeader( - client_->client()->session()->connection()); + client_->client()->client_session()->connection()); EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, header->public_header.connection_id_length); } @@ -1530,7 +1530,7 @@ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - QuicSession* session = client_->client()->session(); + QuicSession* session = client_->client()->client_session(); // Lose the request. SetPacketLossPercentage(100); EXPECT_LT(0, client_->SendRequest("/small_response")); @@ -1574,7 +1574,8 @@ EXPECT_EQ("200", client_->response_headers()->find(":status")->second); // Store the client IP address which was used to send the first request. - QuicIpAddress old_host = client_->client()->GetLatestClientAddress().host(); + QuicIpAddress old_host = + client_->client()->network_helper()->GetLatestClientAddress().host(); // Migrate socket to the new IP address. QuicIpAddress new_host = TestLoopback(2); @@ -1596,7 +1597,8 @@ EXPECT_EQ("200", client_->response_headers()->find(":status")->second); // Store the client address which was used to send the first request. - QuicSocketAddress old_address = client_->client()->GetLatestClientAddress(); + QuicSocketAddress old_address = + client_->client()->network_helper()->GetLatestClientAddress(); int old_fd = client_->client()->GetLatestFD(); // Create a new socket before closing the old one, which will result in a new @@ -1607,32 +1609,38 @@ QuicClientPeer::CleanUpUDPSocket(client_->client(), old_fd); // The packet writer needs to be updated to use the new FD. - client_->client()->CreateQuicPacketWriter(); + client_->client()->network_helper()->CreateQuicPacketWriter(); // Change the internal state of the client and connection to use the new port, // this is done because in a real NAT rebinding the client wouldn't see any // port change, and so expects no change to incoming port. // This is kind of ugly, but needed as we are simply swapping out the client // FD rather than any more complex NAT rebinding simulation. - int new_port = client_->client()->GetLatestClientAddress().port(); + int new_port = + client_->client()->network_helper()->GetLatestClientAddress().port(); QuicClientPeer::SetClientPort(client_->client(), new_port); QuicConnectionPeer::SetSelfAddress( - client_->client()->session()->connection(), - QuicSocketAddress( - client_->client()->session()->connection()->self_address().host(), - new_port)); + client_->client()->client_session()->connection(), + QuicSocketAddress(client_->client() + ->client_session() + ->connection() + ->self_address() + .host(), + new_port)); // Register the new FD for epoll events. int new_fd = client_->client()->GetLatestFD(); EpollServer* eps = client_->epoll_server(); - eps->RegisterFD(new_fd, client_->client(), EPOLLIN | EPOLLOUT | EPOLLET); + eps->RegisterFD(new_fd, client_->client()->epoll_network_helper(), + EPOLLIN | EPOLLOUT | EPOLLET); // Send a second request, using the new FD. EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); EXPECT_EQ("200", client_->response_headers()->find(":status")->second); // Verify that the client's ephemeral port is different. - QuicSocketAddress new_address = client_->client()->GetLatestClientAddress(); + QuicSocketAddress new_address = + client_->client()->network_helper()->GetLatestClientAddress(); EXPECT_EQ(old_address.host(), new_address.host()); EXPECT_NE(old_address.port(), new_address.port()); } @@ -1664,19 +1672,19 @@ // Client should have the right values for server's receive window. EXPECT_EQ(kServerStreamIFCW, client_->client() - ->session() + ->client_session() ->config() ->ReceivedInitialStreamFlowControlWindowBytes()); EXPECT_EQ(kServerSessionIFCW, client_->client() - ->session() + ->client_session() ->config() ->ReceivedInitialSessionFlowControlWindowBytes()); EXPECT_EQ(kServerStreamIFCW, QuicFlowControllerPeer::SendWindowOffset( stream->flow_controller())); EXPECT_EQ(kServerSessionIFCW, QuicFlowControllerPeer::SendWindowOffset( - client_->client()->session()->flow_controller())); + client_->client()->client_session()->flow_controller())); // Server should have the right values for client's receive window. server_thread_->Pause(); @@ -1722,19 +1730,19 @@ // Client should have the right values for server's receive window. EXPECT_EQ(kExpectedStreamIFCW, client_->client() - ->session() + ->client_session() ->config() ->ReceivedInitialStreamFlowControlWindowBytes()); EXPECT_EQ(kExpectedSessionIFCW, client_->client() - ->session() + ->client_session() ->config() ->ReceivedInitialSessionFlowControlWindowBytes()); EXPECT_EQ(kExpectedStreamIFCW, QuicFlowControllerPeer::SendWindowOffset( stream->flow_controller())); EXPECT_EQ(kExpectedSessionIFCW, QuicFlowControllerPeer::SendWindowOffset( - client_->client()->session()->flow_controller())); + client_->client()->client_session()->flow_controller())); } TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) { @@ -1755,27 +1763,29 @@ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); server_thread_->WaitForCryptoHandshakeConfirmed(); - QuicCryptoStream* crypto_stream = - QuicSessionPeer::GetMutableCryptoStream(client_->client()->session()); + QuicCryptoStream* crypto_stream = QuicSessionPeer::GetMutableCryptoStream( + client_->client()->client_session()); EXPECT_LT( QuicFlowControllerPeer::SendWindowSize(crypto_stream->flow_controller()), kStreamIFCW); - EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::SendWindowSize( - client_->client()->session()->flow_controller())); + EXPECT_EQ(kSessionIFCW, + QuicFlowControllerPeer::SendWindowSize( + client_->client()->client_session()->flow_controller())); // Send a request with no body, and verify that the connection level window // has not been affected. EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - QuicHeadersStream* headers_stream = - QuicSpdySessionPeer::GetHeadersStream(client_->client()->session()); - if (!client_->client()->session()->force_hol_blocking()) { + QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream( + client_->client()->client_session()); + if (!client_->client()->client_session()->force_hol_blocking()) { EXPECT_LT(QuicFlowControllerPeer::SendWindowSize( headers_stream->flow_controller()), kStreamIFCW); } - EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::SendWindowSize( - client_->client()->session()->flow_controller())); + EXPECT_EQ(kSessionIFCW, + QuicFlowControllerPeer::SendWindowSize( + client_->client()->client_session()->flow_controller())); // Server should be in a similar state: connection flow control window should // not have any bytes marked as received. @@ -1799,7 +1809,7 @@ server_thread_->WaitForCryptoHandshakeConfirmed(); server_thread_->Pause(); - QuicSpdySession* const client_session = client_->client()->session(); + QuicSpdySession* const client_session = client_->client()->client_session(); QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server_thread_->server()); auto* server_session = static_cast<QuicSpdySession*>( @@ -1921,7 +1931,7 @@ int num_notifications_; }; -class TestResponseListener : public QuicClient::ResponseListener { +class TestResponseListener : public QuicSpdyClientBase::ResponseListener { public: void OnCompleteResponse(QuicStreamId id, const SpdyHeaderBlock& response_headers, @@ -1989,7 +1999,7 @@ // Send the public reset. QuicConnectionId connection_id = - client_->client()->session()->connection()->connection_id(); + client_->client()->client_session()->connection()->connection_id(); QuicPublicResetPacket header; header.public_header.connection_id = connection_id; header.public_header.reset_flag = true; @@ -2003,7 +2013,7 @@ server_thread_->Pause(); server_writer_->WritePacket( packet->data(), packet->length(), server_address_.host(), - client_->client()->GetLatestClientAddress(), nullptr); + client_->client()->network_helper()->GetLatestClientAddress(), nullptr); server_thread_->Resume(); // The request should fail. @@ -2021,7 +2031,7 @@ // Send the public reset. QuicConnectionId incorrect_connection_id = - client_->client()->session()->connection()->connection_id() + 1; + client_->client()->client_session()->connection()->connection_id() + 1; QuicPublicResetPacket header; header.public_header.connection_id = incorrect_connection_id; header.public_header.reset_flag = true; @@ -2031,7 +2041,8 @@ std::unique_ptr<QuicEncryptedPacket> packet( framer.BuildPublicResetPacket(header)); testing::NiceMock<MockQuicConnectionDebugVisitor> visitor; - client_->client()->session()->connection()->set_debug_visitor(&visitor); + client_->client()->client_session()->connection()->set_debug_visitor( + &visitor); EXPECT_CALL(visitor, OnIncorrectConnectionId(incorrect_connection_id)) .Times(1); // We must pause the server's thread in order to call WritePacket without @@ -2039,14 +2050,14 @@ server_thread_->Pause(); server_writer_->WritePacket( packet->data(), packet->length(), server_address_.host(), - client_->client()->GetLatestClientAddress(), nullptr); + client_->client()->network_helper()->GetLatestClientAddress(), nullptr); server_thread_->Resume(); // The connection should be unaffected. EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - client_->client()->session()->connection()->set_debug_visitor(nullptr); + client_->client()->client_session()->connection()->set_debug_visitor(nullptr); } // Send a public reset from the client for a different connection ID. @@ -2056,7 +2067,7 @@ // Send the public reset. QuicConnectionId incorrect_connection_id = - client_->client()->session()->connection()->connection_id() + 1; + client_->client()->client_session()->connection()->connection_id() + 1; QuicPublicResetPacket header; header.public_header.connection_id = incorrect_connection_id; header.public_header.reset_flag = true; @@ -2067,8 +2078,8 @@ framer.BuildPublicResetPacket(header)); client_writer_->WritePacket( packet->data(), packet->length(), - client_->client()->GetLatestClientAddress().host(), server_address_, - nullptr); + client_->client()->network_helper()->GetLatestClientAddress().host(), + server_address_, nullptr); // The connection should be unaffected. EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); @@ -2084,12 +2095,13 @@ // Send the version negotiation packet. QuicConnectionId incorrect_connection_id = - client_->client()->session()->connection()->connection_id() + 1; + client_->client()->client_session()->connection()->connection_id() + 1; std::unique_ptr<QuicEncryptedPacket> packet( QuicFramer::BuildVersionNegotiationPacket(incorrect_connection_id, server_supported_versions_)); testing::NiceMock<MockQuicConnectionDebugVisitor> visitor; - client_->client()->session()->connection()->set_debug_visitor(&visitor); + client_->client()->client_session()->connection()->set_debug_visitor( + &visitor); EXPECT_CALL(visitor, OnIncorrectConnectionId(incorrect_connection_id)) .Times(1); // We must pause the server's thread in order to call WritePacket without @@ -2097,14 +2109,14 @@ server_thread_->Pause(); server_writer_->WritePacket( packet->data(), packet->length(), server_address_.host(), - client_->client()->GetLatestClientAddress(), nullptr); + client_->client()->network_helper()->GetLatestClientAddress(), nullptr); server_thread_->Resume(); // The connection should be unaffected. EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - client_->client()->session()->connection()->set_debug_visitor(nullptr); + client_->client()->client_session()->connection()->set_debug_visitor(nullptr); } // A bad header shouldn't tear down the connection, because the receiver can't @@ -2123,8 +2135,8 @@ 0x11}; client_writer_->WritePacket( &packet[0], sizeof(packet), - client_->client()->GetLatestClientAddress().host(), server_address_, - nullptr); + client_->client()->network_helper()->GetLatestClientAddress().host(), + server_address_, nullptr); // Give the server time to process the packet. base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); // Pause the server so we can access the server's internals without races. @@ -2154,16 +2166,28 @@ // invalid public flags 0xFF, // connection_id - 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, + 0x10, + 0x32, + 0x54, + 0x76, + 0x98, + 0xBA, + 0xDC, + 0xFE, // packet sequence number - 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, + 0xBC, + 0x9A, + 0x78, + 0x56, + 0x34, + 0x12, // private flags 0x00, }; client_writer_->WritePacket( &packet[0], sizeof(packet), - client_->client()->GetLatestClientAddress().host(), server_address_, - nullptr); + client_->client()->network_helper()->GetLatestClientAddress().host(), + server_address_, nullptr); // Give the server time to process the packet. base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); // Pause the server so we can access the server's internals without races. @@ -2189,8 +2213,8 @@ EXPECT_EQ("200", client_->response_headers()->find(":status")->second); std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( - client_->client()->session()->connection()->connection_id(), false, false, - 1, "At least 20 characters.", PACKET_8BYTE_CONNECTION_ID, + client_->client()->client_session()->connection()->connection_id(), false, + false, 1, "At least 20 characters.", PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER)); // Damage the encrypted data. string damaged_packet(packet->data(), packet->length()); @@ -2198,8 +2222,8 @@ QUIC_DLOG(INFO) << "Sending bad packet."; client_writer_->WritePacket( damaged_packet.data(), damaged_packet.length(), - client_->client()->GetLatestClientAddress().host(), server_address_, - nullptr); + client_->client()->network_helper()->GetLatestClientAddress().host(), + server_address_, nullptr); // Give the server time to process the packet. base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); // This error is sent to the connection's OnError (which ignores it), so the @@ -2232,7 +2256,7 @@ // Cancel the stream. stream->Reset(QUIC_STREAM_CANCELLED); - QuicSession* session = client_->client()->session(); + QuicSession* session = client_->client()->client_session(); // Verify canceled stream does not become zombie. EXPECT_TRUE(QuicSessionPeer::zombie_streams(session).empty()); EXPECT_EQ(1u, QuicSessionPeer::closed_streams(session).size()); @@ -2388,7 +2412,7 @@ // A test client stream that drops all received body. class ClientStreamThatDropsBody : public QuicSpdyClientStream { public: - ClientStreamThatDropsBody(QuicStreamId id, QuicClientSession* session) + ClientStreamThatDropsBody(QuicStreamId id, QuicSpdyClientSession* session) : QuicSpdyClientStream(id, session) {} ~ClientStreamThatDropsBody() override {} @@ -2408,18 +2432,18 @@ } }; -class ClientSessionThatDropsBody : public QuicClientSession { +class ClientSessionThatDropsBody : public QuicSpdyClientSession { public: ClientSessionThatDropsBody(const QuicConfig& config, QuicConnection* connection, const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config, QuicClientPushPromiseIndex* push_promise_index) - : QuicClientSession(config, - connection, - server_id, - crypto_config, - push_promise_index) {} + : QuicSpdyClientSession(config, + connection, + server_id, + crypto_config, + push_promise_index) {} ~ClientSessionThatDropsBody() override {} @@ -2446,13 +2470,11 @@ epoll_server) {} ~MockableQuicClientThatDropsBody() override {} - QuicClientSession* CreateQuicClientSession( + std::unique_ptr<QuicSession> CreateQuicClientSession( QuicConnection* connection) override { - auto* session = - new ClientSessionThatDropsBody(*config(), connection, server_id(), - crypto_config(), push_promise_index()); - set_session(session); - return session; + return QuicMakeUnique<ClientSessionThatDropsBody>( + *config(), connection, server_id(), crypto_config(), + push_promise_index()); } }; @@ -2647,14 +2669,14 @@ push_urls, kNumResources, 0); client_->client()->set_response_listener( - std::unique_ptr<QuicClientBase::ResponseListener>( + std::unique_ptr<QuicSpdyClientBase::ResponseListener>( new TestResponseListener)); QUIC_DVLOG(1) << "send request for /push_example"; EXPECT_EQ(kBody, client_->SendSynchronousRequest( "https://example.com/push_example")); - QuicHeadersStream* headers_stream = - QuicSpdySessionPeer::GetHeadersStream(client_->client()->session()); + QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream( + client_->client()->client_session()); QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(headers_stream); // Headers stream's sequencer buffer shouldn't be released because server push // hasn't finished yet. @@ -2687,14 +2709,15 @@ const string kBody = "body content"; size_t const kNumResources = 4; string push_urls[] = { - "https://example.com/font.woff", "https://example.com/script.js", + "https://example.com/font.woff", + "https://example.com/script.js", "https://fonts.example.com/font.woff", "https://example.com/logo-hires.jpg", }; AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, push_urls, kNumResources, 0); client_->client()->set_response_listener( - std::unique_ptr<QuicClientBase::ResponseListener>( + std::unique_ptr<QuicSpdyClientBase::ResponseListener>( new TestResponseListener)); // Send the first request: this will trigger the server to send all the push @@ -2743,7 +2766,7 @@ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, push_urls, kNumResources, 0); client_->client()->set_response_listener( - std::unique_ptr<QuicClientBase::ResponseListener>( + std::unique_ptr<QuicSpdyClientBase::ResponseListener>( new TestResponseListener)); // Send the first request: this will trigger the server to send all the push @@ -2801,7 +2824,7 @@ push_urls, kNumResources, kBodySize); client_->client()->set_response_listener( - std::unique_ptr<QuicClientBase::ResponseListener>( + std::unique_ptr<QuicSpdyClientBase::ResponseListener>( new TestResponseListener)); client_->SendRequest("https://example.com/push_example"); @@ -2911,9 +2934,10 @@ client_.reset(client); static EpollEvent event(EPOLLOUT); client_writer_->Initialize( - QuicConnectionPeer::GetHelper(client_->client()->session()->connection()), + QuicConnectionPeer::GetHelper( + client_->client()->client_session()->connection()), QuicConnectionPeer::GetAlarmFactory( - client_->client()->session()->connection()), + client_->client()->client_session()->connection()), new ClientDelegate(client_->client())); initialized_ = true; ASSERT_TRUE(client_->client()->connected()); @@ -2933,8 +2957,8 @@ // PUSH_PROMISE, its headers stream's sequencer buffer should be released. ASSERT_TRUE(Initialize()); client_->SendSynchronousRequest("/foo"); - QuicHeadersStream* headers_stream = - QuicSpdySessionPeer::GetHeadersStream(client_->client()->session()); + QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream( + client_->client()->client_session()); QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(headers_stream); EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); } @@ -2975,7 +2999,7 @@ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); WindowUpdateObserver observer; QuicConnection* client_connection = - client_->client()->session()->connection(); + client_->client()->client_session()->connection(); client_connection->set_debug_visitor(&observer); QuicVersion version = client_connection->version(); // 100KB body. @@ -3043,7 +3067,7 @@ client_->WaitForResponse(); EXPECT_EQ(kBarResponseBody, client_->response_body()); QuicConnectionStats client_stats = - client_->client()->session()->connection()->GetStats(); + client_->client()->client_session()->connection()->GetStats(); EXPECT_EQ(0u, client_stats.packets_lost); EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); }
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc index aefdc515..f68df5a 100644 --- a/net/tools/quic/quic_client.cc +++ b/net/tools/quic/quic_client.cc
@@ -20,6 +20,7 @@ #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_ptr_util.h" #include "net/tools/quic/platform/impl/quic_socket_utils.h" #include "net/tools/quic/quic_epoll_alarm_factory.h" #include "net/tools/quic/quic_epoll_connection_helper.h" @@ -34,158 +35,62 @@ namespace net { -const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; - QuicClient::QuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const QuicVersionVector& supported_versions, EpollServer* epoll_server, std::unique_ptr<ProofVerifier> proof_verifier) + : QuicClient( + server_address, + server_id, + supported_versions, + QuicConfig(), + epoll_server, + QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)), + std::move(proof_verifier)) {} + +QuicClient::QuicClient( + QuicSocketAddress server_address, + const QuicServerId& server_id, + const QuicVersionVector& supported_versions, + EpollServer* epoll_server, + std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, + std::unique_ptr<ProofVerifier> proof_verifier) : QuicClient(server_address, server_id, supported_versions, QuicConfig(), epoll_server, + std::move(network_helper), std::move(proof_verifier)) {} -QuicClient::QuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const QuicVersionVector& supported_versions, - const QuicConfig& config, - EpollServer* epoll_server, - std::unique_ptr<ProofVerifier> proof_verifier) - : QuicClientBase( +QuicClient::QuicClient( + QuicSocketAddress server_address, + const QuicServerId& server_id, + const QuicVersionVector& supported_versions, + const QuicConfig& config, + EpollServer* epoll_server, + std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, + std::unique_ptr<ProofVerifier> proof_verifier) + : QuicSpdyClientBase( server_id, supported_versions, config, new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE), new QuicEpollAlarmFactory(epoll_server), - std::move(proof_verifier)), - epoll_server_(epoll_server), - packets_dropped_(0), - overflow_supported_(false), - packet_reader_(new QuicPacketReader()) { + std::move(network_helper), + std::move(proof_verifier)) { set_server_address(server_address); } -QuicClient::~QuicClient() { - if (connected()) { - session()->connection()->CloseConnection( - QUIC_PEER_GOING_AWAY, "Client being torn down", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - } +QuicClient::~QuicClient() {} - CleanUpAllUDPSockets(); +QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() { + return static_cast<QuicClientEpollNetworkHelper*>(network_helper()); } -bool QuicClient::CreateUDPSocketAndBind(QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) { - epoll_server_->set_timeout_in_us(50 * 1000); - - int fd = - QuicSocketUtils::CreateUDPSocket(server_address, &overflow_supported_); - if (fd < 0) { - return false; - } - - QuicSocketAddress client_address; - if (bind_to_address.IsInitialized()) { - client_address = QuicSocketAddress(bind_to_address, local_port()); - } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) { - client_address = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port); - } else { - client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port); - } - - sockaddr_storage addr = client_address.generic_address(); - int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)); - if (rc < 0) { - QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno); - return false; - } - - if (client_address.FromSocket(fd) != 0) { - QUIC_LOG(ERROR) << "Unable to get self address. Error: " - << strerror(errno); - } - - fd_address_map_[fd] = client_address; - - epoll_server_->RegisterFD(fd, this, kEpollFlags); - return true; -} - -void QuicClient::CleanUpUDPSocket(int fd) { - CleanUpUDPSocketImpl(fd); - fd_address_map_.erase(fd); -} - -void QuicClient::CleanUpAllUDPSockets() { - for (std::pair<int, QuicSocketAddress> fd_address : fd_address_map_) { - CleanUpUDPSocketImpl(fd_address.first); - } - fd_address_map_.clear(); -} - -void QuicClient::CleanUpUDPSocketImpl(int fd) { - if (fd > -1) { - epoll_server_->UnregisterFD(fd); - int rc = close(fd); - DCHECK_EQ(0, rc); - } -} - -void QuicClient::RunEventLoop() { - base::RunLoop().RunUntilIdle(); - epoll_server_->WaitForEventsAndExecuteCallbacks(); -} - -void QuicClient::OnEvent(int fd, EpollEvent* event) { - DCHECK_EQ(fd, GetLatestFD()); - - if (event->in_events & EPOLLIN) { - bool more_to_read = true; - while (connected() && more_to_read) { - more_to_read = packet_reader_->ReadAndDispatchPackets( - GetLatestFD(), QuicClient::GetLatestClientAddress().port(), - *helper()->GetClock(), this, - overflow_supported_ ? &packets_dropped_ : nullptr); - } - } - if (connected() && (event->in_events & EPOLLOUT)) { - writer()->SetWritable(); - session()->connection()->OnCanWrite(); - } - if (event->in_events & EPOLLERR) { - QUIC_DLOG(INFO) << "Epollerr"; - } -} - -QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { - return new QuicDefaultPacketWriter(GetLatestFD()); -} - -QuicSocketAddress QuicClient::GetLatestClientAddress() const { - if (fd_address_map_.empty()) { - return QuicSocketAddress(); - } - - return fd_address_map_.back().second; -} - -int QuicClient::GetLatestFD() const { - if (fd_address_map_.empty()) { - return -1; - } - - return fd_address_map_.back().first; -} - -void QuicClient::ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) { - session()->ProcessUdpPacket(self_address, peer_address, packet); +const QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() const { + return static_cast<const QuicClientEpollNetworkHelper*>(network_helper()); } } // namespace net
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h index 4c0e673..a236d4b 100644 --- a/net/tools/quic/quic_client.h +++ b/net/tools/quic/quic_client.h
@@ -20,9 +20,11 @@ #include "net/quic/platform/api/quic_containers.h" #include "net/tools/epoll_server/epoll_server.h" #include "net/tools/quic/quic_client_base.h" -#include "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_client_epoll_network_helper.h" #include "net/tools/quic/quic_packet_reader.h" #include "net/tools/quic/quic_process_packet_interface.h" +#include "net/tools/quic/quic_spdy_client_base.h" +#include "net/tools/quic/quic_spdy_client_session.h" namespace net { @@ -32,93 +34,40 @@ class QuicClientPeer; } // namespace test -class QuicClient : public QuicClientBase, - public EpollCallbackInterface, - public ProcessPacketInterface { +class QuicClient : public QuicSpdyClientBase { public: - // Create a quic client, which will have events managed by an externally owned - // EpollServer. + // This will create its own QuicClientEpollNetworkHelper. QuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const QuicVersionVector& supported_versions, EpollServer* epoll_server, std::unique_ptr<ProofVerifier> proof_verifier); + // This will take ownership of a passed in network primitive. + QuicClient(QuicSocketAddress server_address, + const QuicServerId& server_id, + const QuicVersionVector& supported_versions, + EpollServer* epoll_server, + std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, + std::unique_ptr<ProofVerifier> proof_verifier); QuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const QuicVersionVector& supported_versions, const QuicConfig& config, EpollServer* epoll_server, + std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, std::unique_ptr<ProofVerifier> proof_verifier); ~QuicClient() override; - // From EpollCallbackInterface - void OnRegistration(EpollServer* eps, int fd, int event_mask) override {} - void OnModification(int fd, int event_mask) override {} - void OnEvent(int fd, EpollEvent* event) override; - // |fd_| can be unregistered without the client being disconnected. This - // happens in b3m QuicProber where we unregister |fd_| to feed in events to - // the client from the SelectServer. - void OnUnregistration(int fd, bool replaced) override {} - void OnShutdown(EpollServer* eps, int fd) override {} + // Exposed for the quic client test. + int GetLatestFD() const { return epoll_network_helper()->GetLatestFD(); } - // If the client has at least one UDP socket, return the latest created one. - // Otherwise, return -1. - int GetLatestFD() const; - - // From QuicClientBase - QuicSocketAddress GetLatestClientAddress() const override; - - // Implements ProcessPacketInterface. This will be called for each received - // packet. - void ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) override; - - protected: - // From QuicClientBase - QuicPacketWriter* CreateQuicPacketWriter() override; - void RunEventLoop() override; - bool CreateUDPSocketAndBind(QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) override; - void CleanUpAllUDPSockets() override; - - // If |fd| is an open UDP socket, unregister and close it. Otherwise, do - // nothing. - virtual void CleanUpUDPSocket(int fd); - - EpollServer* epoll_server() { return epoll_server_; } - - const QuicLinkedHashMap<int, QuicSocketAddress>& fd_address_map() const { - return fd_address_map_; - } + QuicClientEpollNetworkHelper* epoll_network_helper(); + const QuicClientEpollNetworkHelper* epoll_network_helper() const; private: friend class test::QuicClientPeer; - // Actually clean up |fd|. - void CleanUpUDPSocketImpl(int fd); - - // Listens for events on the client socket. - EpollServer* epoll_server_; - - // Map mapping created UDP sockets to their addresses. By using linked hash - // map, the order of socket creation can be recorded. - QuicLinkedHashMap<int, QuicSocketAddress> fd_address_map_; - - // If overflow_supported_ is true, this will be the number of packets dropped - // during the lifetime of the server. - QuicPacketCount packets_dropped_; - - // True if the kernel supports SO_RXQ_OVFL, the number of packets dropped - // because the socket would otherwise overflow. - bool overflow_supported_; - - // Point to a QuicPacketReader object on the heap. The reader allocates more - // space than allowed on the stack. - std::unique_ptr<QuicPacketReader> packet_reader_; - DISALLOW_COPY_AND_ASSIGN(QuicClient); };
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc index 1a7f087b..408aae63 100644 --- a/net/tools/quic/quic_client_base.cc +++ b/net/tools/quic/quic_client_base.cc
@@ -16,24 +16,14 @@ namespace net { -void QuicClientBase::ClientQuicDataToResend::Resend() { - client_->SendRequest(*headers_, body_, fin_); - headers_ = nullptr; -} - -QuicClientBase::QuicDataToResend::QuicDataToResend( - std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin) - : headers_(std::move(headers)), body_(body), fin_(fin) {} - -QuicClientBase::QuicDataToResend::~QuicDataToResend() {} +QuicClientBase::NetworkHelper::~NetworkHelper() {} QuicClientBase::QuicClientBase(const QuicServerId& server_id, const QuicVersionVector& supported_versions, const QuicConfig& config, QuicConnectionHelperInterface* helper, QuicAlarmFactory* alarm_factory, + std::unique_ptr<NetworkHelper> network_helper, std::unique_ptr<ProofVerifier> proof_verifier) : server_id_(server_id), initialized_(false), @@ -48,39 +38,10 @@ num_sent_client_hellos_(0), connection_error_(QUIC_NO_ERROR), connected_or_attempting_connect_(false), - store_response_(false), - latest_response_code_(-1) {} + network_helper_(std::move(network_helper)) {} QuicClientBase::~QuicClientBase() {} -void QuicClientBase::OnClose(QuicSpdyStream* stream) { - DCHECK(stream != nullptr); - QuicSpdyClientStream* client_stream = - static_cast<QuicSpdyClientStream*>(stream); - - const SpdyHeaderBlock& response_headers = client_stream->response_headers(); - if (response_listener_ != nullptr) { - response_listener_->OnCompleteResponse(stream->id(), response_headers, - client_stream->data()); - } - - // Store response headers and body. - if (store_response_) { - auto status = response_headers.find(":status"); - if (status == response_headers.end() || - !QuicTextUtils::StringToInt(status->second, &latest_response_code_)) { - QUIC_LOG(ERROR) << "Invalid response headers"; - } - latest_response_headers_ = response_headers.DebugString(); - preliminary_response_headers_ = - client_stream->preliminary_headers().DebugString(); - latest_response_header_block_ = response_headers.Clone(); - latest_response_body_ = client_stream->data(); - latest_response_trailers_ = - client_stream->received_trailers().DebugString(); - } -} - bool QuicClientBase::Initialize() { num_sent_client_hellos_ = 0; num_stateless_rejects_received_ = 0; @@ -101,7 +62,8 @@ kSessionMaxRecvWindowSize); } - if (!CreateUDPSocketAndBind(server_address_, bind_to_address_, local_port_)) { + if (!network_helper_->CreateUDPSocketAndBind(server_address_, + bind_to_address_, local_port_)) { return false; } @@ -143,9 +105,7 @@ void QuicClientBase::StartConnect() { DCHECK(initialized_); DCHECK(!connected()); - - QuicPacketWriter* writer = CreateQuicPacketWriter(); - + QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter(); if (connected_or_attempting_connect()) { // If the last error was not a stateless reject, then the queued up data // does not need to be resent. @@ -157,19 +117,24 @@ UpdateStats(); } - CreateQuicClientSession(new QuicConnection( + session_ = CreateQuicClientSession(new QuicConnection( GetNextConnectionId(), server_address(), helper(), alarm_factory(), writer, /* owns_writer= */ false, Perspective::IS_CLIENT, supported_versions())); - + if (initial_max_packet_length_ != 0) { + session()->connection()->SetMaxPacketLength(initial_max_packet_length_); + } // Reset |writer()| after |session()| so that the old writer outlives the old // session. set_writer(writer); - session()->Initialize(); - session()->CryptoConnect(); + InitializeSession(); set_connected_or_attempting_connect(true); } +void QuicClientBase::InitializeSession() { + session()->Initialize(); +} + void QuicClientBase::Disconnect() { DCHECK(initialized_); @@ -181,7 +146,7 @@ ClearDataToResend(); - CleanUpAllUDPSockets(); + network_helper_->CleanUpAllUDPSockets(); initialized_ = false; } @@ -190,87 +155,15 @@ return crypto_config_.proof_verifier(); } -QuicClientSession* QuicClientBase::CreateQuicClientSession( - QuicConnection* connection) { - session_.reset(new QuicClientSession(config_, connection, server_id_, - &crypto_config_, &push_promise_index_)); - if (initial_max_packet_length_ != 0) { - session()->connection()->SetMaxPacketLength(initial_max_packet_length_); - } - return session_.get(); -} - bool QuicClientBase::EncryptionBeingEstablished() { return !session_->IsEncryptionEstablished() && session_->connection()->connected(); } -void QuicClientBase::SendRequest(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - QuicClientPushPromiseIndex::TryHandle* handle; - QuicAsyncStatus rv = push_promise_index()->Try(headers, this, &handle); - if (rv == QUIC_SUCCESS) - return; - - if (rv == QUIC_PENDING) { - // May need to retry request if asynchronous rendezvous fails. - AddPromiseDataToResend(headers, body, fin); - return; - } - - QuicSpdyClientStream* stream = CreateClientStream(); - if (stream == nullptr) { - QUIC_BUG << "stream creation failed!"; - return; - } - stream->SendRequest(headers.Clone(), body, fin); - // Record this in case we need to resend. - MaybeAddDataToResend(headers, body, fin); -} - -void QuicClientBase::SendRequestAndWaitForResponse( - const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - SendRequest(headers, body, fin); - while (WaitForEvents()) { - } -} - -void QuicClientBase::SendRequestsAndWaitForResponse( - const std::vector<string>& url_list) { - for (size_t i = 0; i < url_list.size(); ++i) { - SpdyHeaderBlock headers; - if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { - QUIC_BUG << "Unable to create request"; - continue; - } - SendRequest(headers, "", true); - } - while (WaitForEvents()) { - } -} - -QuicSpdyClientStream* QuicClientBase::CreateClientStream() { - if (!connected()) { - return nullptr; - } - - auto* stream = static_cast<QuicSpdyClientStream*>( - FLAGS_quic_reloadable_flag_quic_refactor_stream_creation - ? session_->MaybeCreateOutgoingDynamicStream(kDefaultPriority) - : session_->CreateOutgoingDynamicStream(kDefaultPriority)); - if (stream) { - stream->set_visitor(this); - } - return stream; -} - bool QuicClientBase::WaitForEvents() { DCHECK(connected()); - RunEventLoop(); + network_helper_->RunEventLoop(); DCHECK(session() != nullptr); if (!connected() && @@ -289,22 +182,36 @@ return false; } - CleanUpAllUDPSockets(); + network_helper_->CleanUpAllUDPSockets(); set_bind_to_address(new_host); - if (!CreateUDPSocketAndBind(server_address_, bind_to_address_, local_port_)) { + if (!network_helper_->CreateUDPSocketAndBind(server_address_, + bind_to_address_, local_port_)) { return false; } - session()->connection()->SetSelfAddress(GetLatestClientAddress()); + session()->connection()->SetSelfAddress( + network_helper_->GetLatestClientAddress()); - QuicPacketWriter* writer = CreateQuicPacketWriter(); + QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter(); set_writer(writer); session()->connection()->SetQuicPacketWriter(writer, false); return true; } +QuicSession* QuicClientBase::session() { + return session_.get(); +} + +QuicClientBase::NetworkHelper* QuicClientBase::network_helper() { + return network_helper_.get(); +} + +const QuicClientBase::NetworkHelper* QuicClientBase::network_helper() const { + return network_helper_.get(); +} + void QuicClientBase::WaitForStreamToClose(QuicStreamId id) { DCHECK(connected()); @@ -339,12 +246,12 @@ // corresponds to the previous connection and should not be used. const int current_session_hellos = !connected_or_attempting_connect_ ? 0 - : session_->GetNumSentClientHellos(); + : GetNumSentClientHellosFromSession(); return num_sent_client_hellos_ + current_session_hellos; } void QuicClientBase::UpdateStats() { - num_sent_client_hellos_ += session()->GetNumSentClientHellos(); + num_sent_client_hellos_ += GetNumSentClientHellosFromSession(); if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { ++num_stateless_rejects_received_; } @@ -358,7 +265,7 @@ // statelessly-rejected connection. return !connected_or_attempting_connect_ ? 0 - : session_->GetNumReceivedServerConfigUpdates(); + : GetNumReceivedServerConfigUpdatesFromSession(); } QuicErrorCode QuicClientBase::connection_error() const { @@ -395,102 +302,4 @@ return QuicRandom::GetInstance()->RandUint64(); } -void QuicClientBase::MaybeAddDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - if (!FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support) { - return; - } - - if (session()->IsCryptoHandshakeConfirmed()) { - // The handshake is confirmed. No need to continue saving requests to - // resend. - data_to_resend_on_connect_.clear(); - return; - } - - // The handshake is not confirmed. Push the data onto the queue of data to - // resend if statelessly rejected. - std::unique_ptr<SpdyHeaderBlock> new_headers( - new SpdyHeaderBlock(headers.Clone())); - std::unique_ptr<QuicDataToResend> data_to_resend( - new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); - MaybeAddQuicDataToResend(std::move(data_to_resend)); -} - -void QuicClientBase::MaybeAddQuicDataToResend( - std::unique_ptr<QuicDataToResend> data_to_resend) { - data_to_resend_on_connect_.push_back(std::move(data_to_resend)); -} - -void QuicClientBase::ClearDataToResend() { - data_to_resend_on_connect_.clear(); -} - -void QuicClientBase::ResendSavedData() { - // Calling Resend will re-enqueue the data, so swap out - // data_to_resend_on_connect_ before iterating. - std::vector<std::unique_ptr<QuicDataToResend>> old_data; - old_data.swap(data_to_resend_on_connect_); - for (const auto& data : old_data) { - data->Resend(); - } -} - -void QuicClientBase::AddPromiseDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - std::unique_ptr<SpdyHeaderBlock> new_headers( - new SpdyHeaderBlock(headers.Clone())); - push_promise_data_to_resend_.reset( - new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); -} - -bool QuicClientBase::CheckVary(const SpdyHeaderBlock& client_request, - const SpdyHeaderBlock& promise_request, - const SpdyHeaderBlock& promise_response) { - return true; -} - -void QuicClientBase::OnRendezvousResult(QuicSpdyStream* stream) { - std::unique_ptr<ClientQuicDataToResend> data_to_resend = - std::move(push_promise_data_to_resend_); - if (stream) { - stream->set_visitor(this); - stream->OnDataAvailable(); - } else if (data_to_resend.get()) { - data_to_resend->Resend(); - } -} - -size_t QuicClientBase::latest_response_code() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_code_; -} - -const string& QuicClientBase::latest_response_headers() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_headers_; -} - -const string& QuicClientBase::preliminary_response_headers() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return preliminary_response_headers_; -} - -const SpdyHeaderBlock& QuicClientBase::latest_response_header_block() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_header_block_; -} - -const string& QuicClientBase::latest_response_body() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_body_; -} - -const string& QuicClientBase::latest_response_trailers() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_trailers_; -} - } // namespace net
diff --git a/net/tools/quic/quic_client_base.h b/net/tools/quic/quic_client_base.h index c95a203..8252e1a5 100644 --- a/net/tools/quic/quic_client_base.h +++ b/net/tools/quic/quic_client_base.h
@@ -16,7 +16,7 @@ #include "net/quic/core/quic_config.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/api/quic_string_piece.h" -#include "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_spdy_client_session.h" #include "net/tools/quic/quic_spdy_client_stream.h" namespace net { @@ -24,46 +24,38 @@ class ProofVerifier; class QuicServerId; -class QuicClientBase : public QuicClientPushPromiseIndex::Delegate, - public QuicSpdyStream::Visitor { +// QuicClientBase handles establishing a connection to the passed in +// server id, including ensuring that it supports the passed in versions +// and config. +// Subclasses derived from this class are responsible for creating the +// actual QuicSession instance, as well as defining functions that +// create and run the underlying network transport. +class QuicClientBase { public: - // A ResponseListener is notified when a complete response is received. - class ResponseListener { + // An interface to various network events that the QuicClient will need to + // interact with. + class NetworkHelper { public: - ResponseListener() {} - virtual ~ResponseListener() {} - virtual void OnCompleteResponse(QuicStreamId id, - const SpdyHeaderBlock& response_headers, - const std::string& response_body) = 0; - }; + virtual ~NetworkHelper(); - // The client uses these objects to keep track of any data to resend upon - // receipt of a stateless reject. Recall that the client API allows callers - // to optimistically send data to the server prior to handshake-confirmation. - // If the client subsequently receives a stateless reject, it must tear down - // its existing session, create a new session, and resend all previously sent - // data. It uses these objects to keep track of all the sent data, and to - // resend the data upon a subsequent connection. - class QuicDataToResend { - public: - // |headers| may be null, since it's possible to send data without headers. - QuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin); + // Runs one iteration of the event loop. + virtual void RunEventLoop() = 0; - virtual ~QuicDataToResend(); + // Used during initialization: creates the UDP socket FD, sets socket + // options, and binds the socket to our address. + virtual bool CreateUDPSocketAndBind(QuicSocketAddress server_address, + QuicIpAddress bind_to_address, + int bind_to_port) = 0; - // Must be overridden by specific classes with the actual method for - // re-sending data. - virtual void Resend() = 0; + // Unregister and close all open UDP sockets. + virtual void CleanUpAllUDPSockets() = 0; - protected: - std::unique_ptr<SpdyHeaderBlock> headers_; - QuicStringPiece body_; - bool fin_; + // If the client has at least one UDP socket, return address of the latest + // created one. Otherwise, return an empty socket address. + virtual QuicSocketAddress GetLatestClientAddress() const = 0; - private: - DISALLOW_COPY_AND_ASSIGN(QuicDataToResend); + // Creates a packet writer to be used for the next connection. + virtual QuicPacketWriter* CreateQuicPacketWriter() = 0; }; QuicClientBase(const QuicServerId& server_id, @@ -71,12 +63,10 @@ const QuicConfig& config, QuicConnectionHelperInterface* helper, QuicAlarmFactory* alarm_factory, + std::unique_ptr<NetworkHelper> network_helper, std::unique_ptr<ProofVerifier> proof_verifier); - ~QuicClientBase() override; - - // QuicSpdyStream::Visitor - void OnClose(QuicSpdyStream* stream) override; + virtual ~QuicClientBase(); // Initializes the client to create a connection. Should be called exactly // once before calling StartConnect or Connect. Returns true if the @@ -92,6 +82,11 @@ // completes. void StartConnect(); + // Calls session()->Initialize(). Subclasses may override this if any extra + // initialization needs to be done. Subclasses should expect that session() + // is non-null and valid. + virtual void InitializeSession(); + // Disconnects from the QUIC server. void Disconnect(); @@ -100,24 +95,6 @@ // the handshake) or if the connection has been closed. bool EncryptionBeingEstablished(); - // Sends an HTTP request and does not wait for response before returning. - void SendRequest(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - // Sends an HTTP request and waits for response before returning. - void SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - // Sends a request simple GET for each URL in |url_list|, and then waits for - // each to complete. - void SendRequestsAndWaitForResponse(const std::vector<std::string>& url_list); - - // Returns a newly created QuicSpdyClientStream, owned by the - // QuicSimpleClient. - virtual QuicSpdyClientStream* CreateClientStream(); - // Wait for events until the stream with the given ID is closed. void WaitForStreamToClose(QuicStreamId id); @@ -132,7 +109,7 @@ // Migrate to a new socket during an active connection. bool MigrateSocket(const QuicIpAddress& new_host); - QuicClientSession* session() { return session_.get(); } + QuicSession* session(); bool connected() const; bool goaway_received() const; @@ -235,36 +212,6 @@ ProofVerifier* proof_verifier() const; - void set_session(QuicClientSession* session) { session_.reset(session); } - - QuicClientPushPromiseIndex* push_promise_index() { - return &push_promise_index_; - } - - bool CheckVary(const SpdyHeaderBlock& client_request, - const SpdyHeaderBlock& promise_request, - const SpdyHeaderBlock& promise_response) override; - void OnRendezvousResult(QuicSpdyStream*) override; - - // If the crypto handshake has not yet been confirmed, adds the data to the - // queue of data to resend if the client receives a stateless reject. - // Otherwise, deletes the data. - void MaybeAddQuicDataToResend( - std::unique_ptr<QuicDataToResend> data_to_resend); - - void set_store_response(bool val) { store_response_ = val; } - - size_t latest_response_code() const; - const std::string& latest_response_headers() const; - const std::string& preliminary_response_headers() const; - const SpdyHeaderBlock& latest_response_header_block() const; - const std::string& latest_response_body() const; - const std::string& latest_response_trailers() const; - - void set_response_listener(std::unique_ptr<ResponseListener> listener) { - response_listener_ = std::move(listener); - } - void set_bind_to_address(QuicIpAddress address) { bind_to_address_ = address; } @@ -281,29 +228,39 @@ server_address_ = server_address; } + QuicConnectionHelperInterface* helper() { return helper_.get(); } + + NetworkHelper* network_helper(); + const NetworkHelper* network_helper() const; + protected: - // Creates a packet writer to be used for the next connection. - virtual QuicPacketWriter* CreateQuicPacketWriter() = 0; + // TODO(rch): Move GetNumSentClientHellosFromSession and + // GetNumReceivedServerConfigUpdatesFromSession into a new/better + // QuicSpdyClientSession class. The current inherits dependencies from + // Spdy. When that happens this class and all its subclasses should + // work with QuicSpdyClientSession instead of QuicSession. + // That will obviate the need for the pure virtual functions below. - // Takes ownership of |connection|. - virtual QuicClientSession* CreateQuicClientSession( - QuicConnection* connection); + // Extract the number of sent client hellos from the session. + virtual int GetNumSentClientHellosFromSession() = 0; - // Runs one iteration of the event loop. - virtual void RunEventLoop() = 0; + // The number of server config updates received. We assume no + // updates can be sent during a previously, statelessly rejected + // connection, so only the latest session is taken into account. + virtual int GetNumReceivedServerConfigUpdatesFromSession() = 0; - // Used during initialization: creates the UDP socket FD, sets socket options, - // and binds the socket to our address. - virtual bool CreateUDPSocketAndBind(QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) = 0; + // If this client supports buffering data, resend it. + virtual void ResendSavedData() = 0; - // Unregister and close all open UDP sockets. - virtual void CleanUpAllUDPSockets() = 0; + // If this client supports buffering data, clear it. + virtual void ClearDataToResend() = 0; - // If the client has at least one UDP socket, return address of the latest - // created one. Otherwise, return an empty socket address. - virtual QuicSocketAddress GetLatestClientAddress() const = 0; + // Takes ownership of |connection|. If you override this function, + // you probably want to call ResetSession() in your destructor. + // TODO(rch): Change the connection parameter to take in a + // std::unique_ptr<QuicConnection> instead. + virtual std::unique_ptr<QuicSession> CreateQuicClientSession( + QuicConnection* connection) = 0; // Generates the next ConnectionId for |server_id_|. By default, if the // cached server config contains a server-designated ID, that ID will be @@ -318,23 +275,6 @@ // connection ID). virtual QuicConnectionId GenerateNewConnectionId(); - // If the crypto handshake has not yet been confirmed, adds the data to the - // queue of data to resend if the client receives a stateless reject. - // Otherwise, deletes the data. - void MaybeAddDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - void ClearDataToResend(); - - void ResendSavedData(); - - void AddPromiseDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - QuicConnectionHelperInterface* helper() { return helper_.get(); } - QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); } void set_num_sent_client_hellos(int num_sent_client_hellos) { @@ -345,29 +285,12 @@ num_stateless_rejects_received_ = num_stateless_rejects_received; } + // Subclasses may need to explicitly clear the session on destruction + // if they create it with objects that will be destroyed before this is. + // You probably want to call this if you override CreateQuicSpdyClientSession. + void ResetSession() { session_.reset(); } + private: - // Specific QuicClient class for storing data to resend. - class ClientQuicDataToResend : public QuicDataToResend { - public: - ClientQuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin, - QuicClientBase* client) - : QuicDataToResend(std::move(headers), body, fin), client_(client) { - DCHECK(headers_); - DCHECK(client); - } - - ~ClientQuicDataToResend() override {} - - void Resend() override; - - private: - QuicClientBase* client_; - - DISALLOW_COPY_AND_ASSIGN(ClientQuicDataToResend); - }; - // |server_id_| is a tuple (hostname, port, is_https) of the server. QuicServerId server_id_; @@ -397,11 +320,8 @@ // Writer used to actually send packets to the wire. Must outlive |session_|. std::unique_ptr<QuicPacketWriter> writer_; - // Index of pending promised streams. Must outlive |session_|. - QuicClientPushPromiseIndex push_promise_index_; - // Session which manages streams. - std::unique_ptr<QuicClientSession> session_; + std::unique_ptr<QuicSession> session_; // This vector contains QUIC versions which we currently support. // This should be ordered such that the highest supported version is the first @@ -435,29 +355,9 @@ // to the previous client-level connection. bool connected_or_attempting_connect_; - // If true, store the latest response code, headers, and body. - bool store_response_; - // HTTP response code from most recent response. - int latest_response_code_; - // HTTP/2 headers from most recent response. - std::string latest_response_headers_; - // preliminary 100 Continue HTTP/2 headers from most recent response, if any. - std::string preliminary_response_headers_; - // HTTP/2 headers from most recent response. - SpdyHeaderBlock latest_response_header_block_; - // Body of most recent response. - std::string latest_response_body_; - // HTTP/2 trailers from most recent response. - std::string latest_response_trailers_; - - // Listens for full responses. - std::unique_ptr<ResponseListener> response_listener_; - - // Keeps track of any data that must be resent upon a subsequent successful - // connection, in case the client receives a stateless reject. - std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_; - - std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_; + // The network helper used to create sockets and manage the event loop. + // Not owned by this class. + std::unique_ptr<NetworkHelper> network_helper_; DISALLOW_COPY_AND_ASSIGN(QuicClientBase); };
diff --git a/net/tools/quic/quic_client_epoll_network_helper.cc b/net/tools/quic/quic_client_epoll_network_helper.cc new file mode 100644 index 0000000..57b064b --- /dev/null +++ b/net/tools/quic/quic_client_epoll_network_helper.cc
@@ -0,0 +1,185 @@ +// 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 "net/tools/quic/quic_client_epoll_network_helper.h" + +#include <errno.h> +#include <netinet/in.h> +#include <string.h> +#include <sys/epoll.h> +#include <sys/socket.h> +#include <unistd.h> + +#include "base/run_loop.h" +#include "net/quic/core/crypto/quic_random.h" +#include "net/quic/core/quic_connection.h" +#include "net/quic/core/quic_data_reader.h" +#include "net/quic/core/quic_packets.h" +#include "net/quic/core/quic_server_id.h" +#include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_ptr_util.h" +#include "net/tools/quic/platform/impl/quic_socket_utils.h" +#include "net/tools/quic/quic_epoll_alarm_factory.h" +#include "net/tools/quic/quic_epoll_connection_helper.h" + +#ifndef SO_RXQ_OVFL +#define SO_RXQ_OVFL 40 +#endif + +// TODO(rtenneti): Add support for MMSG_MORE. +#define MMSG_MORE 0 +using std::string; + +namespace net { + +namespace { +const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; +} // namespace + +QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper( + EpollServer* epoll_server, + QuicClientBase* client) + : epoll_server_(epoll_server), + packets_dropped_(0), + overflow_supported_(false), + packet_reader_(new QuicPacketReader()), + client_(client) {} + +QuicClientEpollNetworkHelper::~QuicClientEpollNetworkHelper() { + if (client_->connected()) { + client_->session()->connection()->CloseConnection( + QUIC_PEER_GOING_AWAY, "Client being torn down", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + } + + CleanUpAllUDPSockets(); +} + +bool QuicClientEpollNetworkHelper::CreateUDPSocketAndBind( + QuicSocketAddress server_address, + QuicIpAddress bind_to_address, + int bind_to_port) { + epoll_server_->set_timeout_in_us(50 * 1000); + + int fd = + QuicSocketUtils::CreateUDPSocket(server_address, &overflow_supported_); + if (fd < 0) { + return false; + } + + QuicSocketAddress client_address; + if (bind_to_address.IsInitialized()) { + client_address = QuicSocketAddress(bind_to_address, client_->local_port()); + } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) { + client_address = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port); + } else { + client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port); + } + + sockaddr_storage addr = client_address.generic_address(); + int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)); + if (rc < 0) { + QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno); + return false; + } + + if (client_address.FromSocket(fd) != 0) { + QUIC_LOG(ERROR) << "Unable to get self address. Error: " + << strerror(errno); + } + + fd_address_map_[fd] = client_address; + + epoll_server_->RegisterFD(fd, this, kEpollFlags); + return true; +} + +void QuicClientEpollNetworkHelper::CleanUpUDPSocket(int fd) { + CleanUpUDPSocketImpl(fd); + fd_address_map_.erase(fd); +} + +void QuicClientEpollNetworkHelper::CleanUpAllUDPSockets() { + for (std::pair<int, QuicSocketAddress> fd_address : fd_address_map_) { + CleanUpUDPSocketImpl(fd_address.first); + } + fd_address_map_.clear(); +} + +void QuicClientEpollNetworkHelper::CleanUpUDPSocketImpl(int fd) { + if (fd > -1) { + epoll_server_->UnregisterFD(fd); + int rc = close(fd); + DCHECK_EQ(0, rc); + } +} + +void QuicClientEpollNetworkHelper::RunEventLoop() { + base::RunLoop().RunUntilIdle(); + epoll_server_->WaitForEventsAndExecuteCallbacks(); +} + +void QuicClientEpollNetworkHelper::OnRegistration(EpollServer* eps, + int fd, + int event_mask) {} +void QuicClientEpollNetworkHelper::OnModification(int fd, int event_mask) {} +void QuicClientEpollNetworkHelper::OnUnregistration(int fd, bool replaced) {} +void QuicClientEpollNetworkHelper::OnShutdown(EpollServer* eps, int fd) {} + +void QuicClientEpollNetworkHelper::OnEvent(int fd, EpollEvent* event) { + DCHECK_EQ(fd, GetLatestFD()); + + if (event->in_events & EPOLLIN) { + bool more_to_read = true; + while (client_->connected() && more_to_read) { + more_to_read = packet_reader_->ReadAndDispatchPackets( + GetLatestFD(), GetLatestClientAddress().port(), + *client_->helper()->GetClock(), this, + overflow_supported_ ? &packets_dropped_ : nullptr); + } + } + if (client_->connected() && (event->in_events & EPOLLOUT)) { + client_->writer()->SetWritable(); + client_->session()->connection()->OnCanWrite(); + } + if (event->in_events & EPOLLERR) { + QUIC_DLOG(INFO) << "Epollerr"; + } +} + +QuicPacketWriter* QuicClientEpollNetworkHelper::CreateQuicPacketWriter() { + return new QuicDefaultPacketWriter(GetLatestFD()); +} + +void QuicClientEpollNetworkHelper::SetClientPort(int port) { + fd_address_map_.back().second = + QuicSocketAddress(GetLatestClientAddress().host(), port); +} + +QuicSocketAddress QuicClientEpollNetworkHelper::GetLatestClientAddress() const { + if (fd_address_map_.empty()) { + return QuicSocketAddress(); + } + + return fd_address_map_.back().second; +} + +int QuicClientEpollNetworkHelper::GetLatestFD() const { + if (fd_address_map_.empty()) { + return -1; + } + + return fd_address_map_.back().first; +} + +void QuicClientEpollNetworkHelper::ProcessPacket( + const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, + const QuicReceivedPacket& packet) { + client_->session()->ProcessUdpPacket(self_address, peer_address, packet); +} + +} // namespace net
diff --git a/net/tools/quic/quic_client_epoll_network_helper.h b/net/tools/quic/quic_client_epoll_network_helper.h new file mode 100644 index 0000000..bc2fa1ba --- /dev/null +++ b/net/tools/quic/quic_client_epoll_network_helper.h
@@ -0,0 +1,125 @@ +// 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. +// +// An implementation of the QuicClientBase::NetworkHelper +// that is based off the epoll server. + +#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_EPOLL_NETWORK_HELPER_H_ +#define NET_TOOLS_QUIC_QUIC_CLIENT_EPOLL_NETWORK_HELPER_H_ + +#include <cstdint> +#include <memory> +#include <string> + +#include "base/command_line.h" +#include "base/macros.h" +#include "net/quic/core/quic_client_push_promise_index.h" +#include "net/quic/core/quic_config.h" +#include "net/quic/core/quic_spdy_stream.h" +#include "net/quic/platform/api/quic_containers.h" +#include "net/tools/epoll_server/epoll_server.h" +#include "net/tools/quic/quic_client_base.h" +#include "net/tools/quic/quic_packet_reader.h" +#include "net/tools/quic/quic_process_packet_interface.h" +#include "net/tools/quic/quic_spdy_client_base.h" +#include "net/tools/quic/quic_spdy_client_session.h" + +namespace net { + +namespace test { +class QuicClientPeer; +} // namespace test + +// An implementation of the QuicClientBase::NetworkHelper based off +// the epoll server. +class QuicClientEpollNetworkHelper : public QuicClientBase::NetworkHelper, + public EpollCallbackInterface, + public ProcessPacketInterface { + public: + // Create a quic client, which will have events managed by an externally owned + // EpollServer. + QuicClientEpollNetworkHelper(EpollServer* epoll_server, + QuicClientBase* client); + + ~QuicClientEpollNetworkHelper() override; + + // From EpollCallbackInterface + void OnRegistration(EpollServer* eps, int fd, int event_mask) override; + void OnModification(int fd, int event_mask) override; + void OnEvent(int fd, EpollEvent* event) override; + // |fd_| can be unregistered without the client being disconnected. This + // happens in b3m QuicProber where we unregister |fd_| to feed in events to + // the client from the SelectServer. + void OnUnregistration(int fd, bool replaced) override; + void OnShutdown(EpollServer* eps, int fd) override; + + // From ProcessPacketInterface. This will be called for each received + // packet. + void ProcessPacket(const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, + const QuicReceivedPacket& packet) override; + + // From NetworkHelper. + void RunEventLoop() override; + bool CreateUDPSocketAndBind(QuicSocketAddress server_address, + QuicIpAddress bind_to_address, + int bind_to_port) override; + void CleanUpAllUDPSockets() override; + QuicSocketAddress GetLatestClientAddress() const override; + QuicPacketWriter* CreateQuicPacketWriter() override; + + // Accessors provided for convenience, not part of any interface. + + EpollServer* epoll_server() { return epoll_server_; } + + const QuicLinkedHashMap<int, QuicSocketAddress>& fd_address_map() const { + return fd_address_map_; + } + + // If the client has at least one UDP socket, return the latest created one. + // Otherwise, return -1. + int GetLatestFD() const; + + QuicClientBase* client() { return client_; } + + private: + friend class test::QuicClientPeer; + + // Used for testing. + void SetClientPort(int port); + + // If |fd| is an open UDP socket, unregister and close it. Otherwise, do + // nothing. + void CleanUpUDPSocket(int fd); + + // Actually clean up |fd|. + void CleanUpUDPSocketImpl(int fd); + + // Listens for events on the client socket. + EpollServer* epoll_server_; + + // Map mapping created UDP sockets to their addresses. By using linked hash + // map, the order of socket creation can be recorded. + QuicLinkedHashMap<int, QuicSocketAddress> fd_address_map_; + + // If overflow_supported_ is true, this will be the number of packets dropped + // during the lifetime of the server. + QuicPacketCount packets_dropped_; + + // True if the kernel supports SO_RXQ_OVFL, the number of packets dropped + // because the socket would otherwise overflow. + bool overflow_supported_; + + // Point to a QuicPacketReader object on the heap. The reader allocates more + // space than allowed on the stack. + std::unique_ptr<QuicPacketReader> packet_reader_; + + QuicClientBase* client_; + + DISALLOW_COPY_AND_ASSIGN(QuicClientEpollNetworkHelper); +}; + +} // namespace net + +#endif // NET_TOOLS_QUIC_QUIC_CLIENT_EPOLL_NETWORK_HELPER_H_
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.cc b/net/tools/quic/quic_client_message_loop_network_helper.cc new file mode 100644 index 0000000..053979fa --- /dev/null +++ b/net/tools/quic/quic_client_message_loop_network_helper.cc
@@ -0,0 +1,146 @@ +// 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 "net/tools/quic/quic_client_message_loop_network_helper.h" + +#include <utility> + +#include "base/logging.h" +#include "base/run_loop.h" +#include "base/threading/thread_task_runner_handle.h" +#include "net/base/net_errors.h" +#include "net/http/http_request_info.h" +#include "net/http/http_response_info.h" +#include "net/log/net_log_source.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/chromium/quic_chromium_alarm_factory.h" +#include "net/quic/chromium/quic_chromium_connection_helper.h" +#include "net/quic/chromium/quic_chromium_packet_reader.h" +#include "net/quic/chromium/quic_chromium_packet_writer.h" +#include "net/quic/core/crypto/quic_random.h" +#include "net/quic/core/quic_connection.h" +#include "net/quic/core/quic_packets.h" +#include "net/quic/core/quic_server_id.h" +#include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_ptr_util.h" +#include "net/socket/udp_client_socket.h" +#include "net/spdy/chromium/spdy_http_utils.h" +#include "net/spdy/core/spdy_header_block.h" + +using std::string; + +namespace net { + +QuicClientMessageLooplNetworkHelper::QuicClientMessageLooplNetworkHelper( + QuicChromiumClock* clock, + QuicClientBase* client) + : packet_reader_started_(false), clock_(clock), client_(client) {} + +QuicClientMessageLooplNetworkHelper::~QuicClientMessageLooplNetworkHelper() {} + +bool QuicClientMessageLooplNetworkHelper::CreateUDPSocketAndBind( + QuicSocketAddress server_address, + QuicIpAddress bind_to_address, + int bind_to_port) { + std::unique_ptr<UDPClientSocket> socket( + new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(), + &net_log_, NetLogSource())); + + if (bind_to_address.IsInitialized()) { + client_address_ = QuicSocketAddress(bind_to_address, client_->local_port()); + } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) { + client_address_ = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port); + } else { + client_address_ = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port); + } + + int rc = socket->Connect(server_address.impl().socket_address()); + if (rc != OK) { + LOG(ERROR) << "Connect failed: " << ErrorToShortString(rc); + return false; + } + + rc = socket->SetReceiveBufferSize(kDefaultSocketReceiveBuffer); + if (rc != OK) { + LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToShortString(rc); + return false; + } + + rc = socket->SetSendBufferSize(kDefaultSocketReceiveBuffer); + if (rc != OK) { + LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToShortString(rc); + return false; + } + + IPEndPoint address; + rc = socket->GetLocalAddress(&address); + if (rc != OK) { + LOG(ERROR) << "GetLocalAddress failed: " << ErrorToShortString(rc); + return false; + } + client_address_ = QuicSocketAddress(QuicSocketAddressImpl(address)); + + socket_.swap(socket); + packet_reader_.reset(new QuicChromiumPacketReader( + socket_.get(), clock_, this, kQuicYieldAfterPacketsRead, + QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds), + NetLogWithSource())); + + if (socket != nullptr) { + socket->Close(); + } + + return true; +} + +void QuicClientMessageLooplNetworkHelper::CleanUpAllUDPSockets() { + client_->reset_writer(); + packet_reader_.reset(); + packet_reader_started_ = false; +} + +void QuicClientMessageLooplNetworkHelper::StartPacketReaderIfNotStarted() { + if (!packet_reader_started_) { + packet_reader_->StartReading(); + packet_reader_started_ = true; + } +} + +void QuicClientMessageLooplNetworkHelper::RunEventLoop() { + StartPacketReaderIfNotStarted(); + base::RunLoop().RunUntilIdle(); +} + +QuicPacketWriter* +QuicClientMessageLooplNetworkHelper::CreateQuicPacketWriter() { + return new QuicChromiumPacketWriter(socket_.get()); +} + +void QuicClientMessageLooplNetworkHelper::OnReadError( + int result, + const DatagramClientSocket* socket) { + LOG(ERROR) << "QuicSimpleClient read failed: " << ErrorToShortString(result); + client_->Disconnect(); +} + +QuicSocketAddress QuicClientMessageLooplNetworkHelper::GetLatestClientAddress() + const { + return client_address_; +} + +bool QuicClientMessageLooplNetworkHelper::OnPacket( + const QuicReceivedPacket& packet, + const QuicSocketAddress& local_address, + const QuicSocketAddress& peer_address) { + client_->session()->connection()->ProcessUdpPacket(local_address, + peer_address, packet); + if (!client_->session()->connection()->connected()) { + return false; + } + + return true; +} + +} // namespace net
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.h b/net/tools/quic/quic_client_message_loop_network_helper.h new file mode 100644 index 0000000..891f19f --- /dev/null +++ b/net/tools/quic/quic_client_message_loop_network_helper.h
@@ -0,0 +1,84 @@ +// 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. +// +// A toy client, which connects to a specified port and sends QUIC +// request to that endpoint. + +#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_MESSAGE_LOOP_NETWORK_HELPER_H_ +#define NET_TOOLS_QUIC_QUIC_CLIENT_MESSAGE_LOOP_NETWORK_HELPER_H_ + +#include <stddef.h> + +#include <memory> +#include <string> + +#include "base/command_line.h" +#include "base/macros.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" +#include "net/http/http_response_headers.h" +#include "net/log/net_log.h" +#include "net/quic/chromium/quic_chromium_packet_reader.h" +#include "net/quic/core/quic_config.h" +#include "net/quic/core/quic_spdy_stream.h" +#include "net/quic/platform/impl/quic_chromium_clock.h" +#include "net/tools/quic/quic_spdy_client_base.h" + +namespace net { + +class UDPClientSocket; + +// An implementation of the QuicClientBase::NetworkHelper based off +// the chromium epoll server. +class QuicClientMessageLooplNetworkHelper + : public QuicClientBase::NetworkHelper, + public QuicChromiumPacketReader::Visitor { + public: + // Create a quic client, which will have events managed by an externally owned + // EpollServer. + QuicClientMessageLooplNetworkHelper(QuicChromiumClock* clock, + QuicClientBase* client); + + ~QuicClientMessageLooplNetworkHelper() override; + + // QuicChromiumPacketReader::Visitor + void OnReadError(int result, const DatagramClientSocket* socket) override; + bool OnPacket(const QuicReceivedPacket& packet, + const QuicSocketAddress& local_address, + const QuicSocketAddress& peer_address) override; + + // From NetworkHelper. + void RunEventLoop() override; + bool CreateUDPSocketAndBind(QuicSocketAddress server_address, + QuicIpAddress bind_to_address, + int bind_to_port) override; + void CleanUpAllUDPSockets() override; + QuicSocketAddress GetLatestClientAddress() const override; + QuicPacketWriter* CreateQuicPacketWriter() override; + + private: + void StartPacketReaderIfNotStarted(); + + // Address of the client if the client is connected to the server. + QuicSocketAddress client_address_; + + // UDP socket connected to the server. + std::unique_ptr<UDPClientSocket> socket_; + + // The log used for the sockets. + NetLog net_log_; + + std::unique_ptr<QuicChromiumPacketReader> packet_reader_; + + bool packet_reader_started_; + + QuicChromiumClock* clock_; + QuicClientBase* client_; + + DISALLOW_COPY_AND_ASSIGN(QuicClientMessageLooplNetworkHelper); +}; + +} // namespace net + +#endif // NET_TOOLS_QUIC_QUIC_CLIENT_MESSAGE_LOOP_NETWORK_HELPER_H_
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index e322b68..0fec950 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -1003,7 +1003,10 @@ break; case StatelessRejector::REJECTED: { - DCHECK_EQ(framer_.version(), first_version); + QUIC_BUG_IF(first_version != framer_.version()) + << "SREJ: Client's version: " << QuicVersionToString(first_version) + << " is different from current dispatcher framer's version: " + << QuicVersionToString(framer_.version()); StatelessConnectionTerminator terminator(rejector->connection_id(), &framer_, helper(), time_wait_list_manager_.get());
diff --git a/net/tools/quic/quic_epoll_alarm_factory_test.cc b/net/tools/quic/quic_epoll_alarm_factory_test.cc index 1ee2b84..2e0f743a4 100644 --- a/net/tools/quic/quic_epoll_alarm_factory_test.cc +++ b/net/tools/quic/quic_epoll_alarm_factory_test.cc
@@ -40,6 +40,10 @@ QuicConnectionArena arena_; }; +INSTANTIATE_TEST_CASE_P(UseArena, + QuicEpollAlarmFactoryTest, + ::testing::ValuesIn({true, false})); + TEST_P(QuicEpollAlarmFactoryTest, CreateAlarm) { QuicArenaScopedPtr<TestDelegate> delegate = QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc index cd47622..12b511f6 100644 --- a/net/tools/quic/quic_simple_client.cc +++ b/net/tools/quic/quic_simple_client.cc
@@ -24,6 +24,7 @@ #include "net/quic/core/quic_server_id.h" #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_ptr_util.h" #include "net/socket/udp_client_socket.h" #include "net/spdy/chromium/spdy_http_utils.h" #include "net/spdy/core/spdy_header_block.h" @@ -37,14 +38,16 @@ const QuicServerId& server_id, const QuicVersionVector& supported_versions, std::unique_ptr<ProofVerifier> proof_verifier) - : QuicClientBase(server_id, - supported_versions, - QuicConfig(), - CreateQuicConnectionHelper(), - CreateQuicAlarmFactory(), - std::move(proof_verifier)), + : QuicSpdyClientBase( + server_id, + supported_versions, + QuicConfig(), + CreateQuicConnectionHelper(), + CreateQuicAlarmFactory(), + QuicWrapUnique( + new QuicClientMessageLooplNetworkHelper(&clock_, this)), + std::move(proof_verifier)), initialized_(false), - packet_reader_started_(false), weak_factory_(this) { set_server_address(server_address); } @@ -57,79 +60,6 @@ } } -bool QuicSimpleClient::CreateUDPSocketAndBind(QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) { - std::unique_ptr<UDPClientSocket> socket( - new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(), - &net_log_, NetLogSource())); - - if (bind_to_address.IsInitialized()) { - client_address_ = QuicSocketAddress(bind_to_address, local_port()); - } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) { - client_address_ = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port); - } else { - client_address_ = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port); - } - - int rc = socket->Connect(server_address.impl().socket_address()); - if (rc != OK) { - LOG(ERROR) << "Connect failed: " << ErrorToShortString(rc); - return false; - } - - rc = socket->SetReceiveBufferSize(kDefaultSocketReceiveBuffer); - if (rc != OK) { - LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToShortString(rc); - return false; - } - - rc = socket->SetSendBufferSize(kDefaultSocketReceiveBuffer); - if (rc != OK) { - LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToShortString(rc); - return false; - } - - IPEndPoint address; - rc = socket->GetLocalAddress(&address); - if (rc != OK) { - LOG(ERROR) << "GetLocalAddress failed: " << ErrorToShortString(rc); - return false; - } - client_address_ = QuicSocketAddress(QuicSocketAddressImpl(address)); - - socket_.swap(socket); - packet_reader_.reset(new QuicChromiumPacketReader( - socket_.get(), &clock_, this, kQuicYieldAfterPacketsRead, - QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds), - NetLogWithSource())); - - if (socket != nullptr) { - socket->Close(); - } - - return true; -} - -void QuicSimpleClient::CleanUpAllUDPSockets() { - reset_writer(); - packet_reader_.reset(); - packet_reader_started_ = false; - -} - -void QuicSimpleClient::StartPacketReaderIfNotStarted() { - if (!packet_reader_started_) { - packet_reader_->StartReading(); - packet_reader_started_ = true; - } -} - -void QuicSimpleClient::RunEventLoop() { - StartPacketReaderIfNotStarted(); - base::RunLoop().RunUntilIdle(); -} - QuicChromiumConnectionHelper* QuicSimpleClient::CreateQuicConnectionHelper() { return new QuicChromiumConnectionHelper(&clock_, QuicRandom::GetInstance()); } @@ -139,30 +69,4 @@ &clock_); } -QuicPacketWriter* QuicSimpleClient::CreateQuicPacketWriter() { - return new QuicChromiumPacketWriter(socket_.get()); -} - -void QuicSimpleClient::OnReadError(int result, - const DatagramClientSocket* socket) { - LOG(ERROR) << "QuicSimpleClient read failed: " << ErrorToShortString(result); - Disconnect(); -} - -QuicSocketAddress QuicSimpleClient::GetLatestClientAddress() const { - return client_address_; -} - -bool QuicSimpleClient::OnPacket(const QuicReceivedPacket& packet, - const QuicSocketAddress& local_address, - const QuicSocketAddress& peer_address) { - session()->connection()->ProcessUdpPacket(local_address, peer_address, - packet); - if (!session()->connection()->connected()) { - return false; - } - - return true; -} - } // namespace net
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h index b0c25ca..1aecc2a2 100644 --- a/net/tools/quic/quic_simple_client.h +++ b/net/tools/quic/quic_simple_client.h
@@ -23,21 +23,19 @@ #include "net/quic/core/quic_config.h" #include "net/quic/core/quic_spdy_stream.h" #include "net/quic/platform/impl/quic_chromium_clock.h" -#include "net/tools/quic/quic_client_base.h" +#include "net/tools/quic/quic_client_message_loop_network_helper.h" +#include "net/tools/quic/quic_spdy_client_base.h" namespace net { class QuicChromiumAlarmFactory; class QuicChromiumConnectionHelper; -class UDPClientSocket; - namespace test { class QuicClientPeer; } // namespace test -class QuicSimpleClient : public QuicClientBase, - public QuicChromiumPacketReader::Visitor { +class QuicSimpleClient : public QuicSpdyClientBase { public: // Create a quic client, which will have events managed by the message loop. QuicSimpleClient(QuicSocketAddress server_address, @@ -47,54 +45,18 @@ ~QuicSimpleClient() override; - // QuicChromiumPacketReader::Visitor - void OnReadError(int result, const DatagramClientSocket* socket) override; - bool OnPacket(const QuicReceivedPacket& packet, - const QuicSocketAddress& local_address, - const QuicSocketAddress& peer_address) override; - - // From QuicClientBase - QuicSocketAddress GetLatestClientAddress() const override; - - protected: - // From QuicClientBase - QuicPacketWriter* CreateQuicPacketWriter() override; - void RunEventLoop() override; - bool CreateUDPSocketAndBind(QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) override; - void CleanUpAllUDPSockets() override; - private: friend class net::test::QuicClientPeer; QuicChromiumAlarmFactory* CreateQuicAlarmFactory(); QuicChromiumConnectionHelper* CreateQuicConnectionHelper(); - // Read a UDP packet and hand it to the framer. - bool ReadAndProcessPacket(); - - void StartPacketReaderIfNotStarted(); - // Used by |helper_| to time alarms. QuicChromiumClock clock_; - // Address of the client if the client is connected to the server. - QuicSocketAddress client_address_; - - // UDP socket connected to the server. - std::unique_ptr<UDPClientSocket> socket_; - // Tracks if the client is initialized to connect. bool initialized_; - // The log used for the sockets. - NetLog net_log_; - - std::unique_ptr<QuicChromiumPacketReader> packet_reader_; - - bool packet_reader_started_; - base::WeakPtrFactory<QuicSimpleClient> weak_factory_; DISALLOW_COPY_AND_ASSIGN(QuicSimpleClient);
diff --git a/net/tools/quic/quic_spdy_client_base.cc b/net/tools/quic/quic_spdy_client_base.cc new file mode 100644 index 0000000..7fc0ab6 --- /dev/null +++ b/net/tools/quic/quic_spdy_client_base.cc
@@ -0,0 +1,270 @@ +// 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 "net/tools/quic/quic_spdy_client_base.h" + +#include "net/quic/core/crypto/quic_random.h" +#include "net/quic/core/quic_server_id.h" +#include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" +#include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_ptr_util.h" +#include "net/quic/platform/api/quic_text_utils.h" + +using base::StringToInt; +using std::string; + +namespace net { + +void QuicSpdyClientBase::ClientQuicDataToResend::Resend() { + client_->SendRequest(*headers_, body_, fin_); + headers_ = nullptr; +} + +QuicSpdyClientBase::QuicDataToResend::QuicDataToResend( + std::unique_ptr<SpdyHeaderBlock> headers, + QuicStringPiece body, + bool fin) + : headers_(std::move(headers)), body_(body), fin_(fin) {} + +QuicSpdyClientBase::QuicDataToResend::~QuicDataToResend() {} + +QuicSpdyClientBase::QuicSpdyClientBase( + const QuicServerId& server_id, + const QuicVersionVector& supported_versions, + const QuicConfig& config, + QuicConnectionHelperInterface* helper, + QuicAlarmFactory* alarm_factory, + std::unique_ptr<NetworkHelper> network_helper, + std::unique_ptr<ProofVerifier> proof_verifier) + : QuicClientBase(server_id, + supported_versions, + config, + helper, + alarm_factory, + std::move(network_helper), + std::move(proof_verifier)), + store_response_(false), + latest_response_code_(-1) {} + +QuicSpdyClientBase::~QuicSpdyClientBase() { + // We own the push promise index. We need to explicitly kill + // the session before the push promise index goes out of scope. + ResetSession(); +} + +QuicSpdyClientSession* QuicSpdyClientBase::client_session() { + return static_cast<QuicSpdyClientSession*>(QuicClientBase::session()); +} + +void QuicSpdyClientBase::InitializeSession() { + client_session()->Initialize(); + client_session()->CryptoConnect(); +} + +void QuicSpdyClientBase::OnClose(QuicSpdyStream* stream) { + DCHECK(stream != nullptr); + QuicSpdyClientStream* client_stream = + static_cast<QuicSpdyClientStream*>(stream); + + const SpdyHeaderBlock& response_headers = client_stream->response_headers(); + if (response_listener_ != nullptr) { + response_listener_->OnCompleteResponse(stream->id(), response_headers, + client_stream->data()); + } + + // Store response headers and body. + if (store_response_) { + auto status = response_headers.find(":status"); + if (status == response_headers.end() || + !QuicTextUtils::StringToInt(status->second, &latest_response_code_)) { + QUIC_LOG(ERROR) << "Invalid response headers"; + } + latest_response_headers_ = response_headers.DebugString(); + preliminary_response_headers_ = + client_stream->preliminary_headers().DebugString(); + latest_response_header_block_ = response_headers.Clone(); + latest_response_body_ = client_stream->data(); + latest_response_trailers_ = + client_stream->received_trailers().DebugString(); + } +} + +std::unique_ptr<QuicSession> QuicSpdyClientBase::CreateQuicClientSession( + QuicConnection* connection) { + return QuicMakeUnique<QuicSpdyClientSession>(*config(), connection, + server_id(), crypto_config(), + &push_promise_index_); +} + +void QuicSpdyClientBase::SendRequest(const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin) { + QuicClientPushPromiseIndex::TryHandle* handle; + QuicAsyncStatus rv = push_promise_index()->Try(headers, this, &handle); + if (rv == QUIC_SUCCESS) + return; + + if (rv == QUIC_PENDING) { + // May need to retry request if asynchronous rendezvous fails. + AddPromiseDataToResend(headers, body, fin); + return; + } + + QuicSpdyClientStream* stream = CreateClientStream(); + if (stream == nullptr) { + QUIC_BUG << "stream creation failed!"; + return; + } + stream->SendRequest(headers.Clone(), body, fin); + // Record this in case we need to resend. + MaybeAddDataToResend(headers, body, fin); +} + +void QuicSpdyClientBase::SendRequestAndWaitForResponse( + const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin) { + SendRequest(headers, body, fin); + while (WaitForEvents()) { + } +} + +void QuicSpdyClientBase::SendRequestsAndWaitForResponse( + const std::vector<string>& url_list) { + for (size_t i = 0; i < url_list.size(); ++i) { + SpdyHeaderBlock headers; + if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { + QUIC_BUG << "Unable to create request"; + continue; + } + SendRequest(headers, "", true); + } + while (WaitForEvents()) { + } +} + +QuicSpdyClientStream* QuicSpdyClientBase::CreateClientStream() { + if (!connected()) { + return nullptr; + } + + auto* stream = static_cast<QuicSpdyClientStream*>( + FLAGS_quic_reloadable_flag_quic_refactor_stream_creation + ? client_session()->MaybeCreateOutgoingDynamicStream(kDefaultPriority) + : client_session()->CreateOutgoingDynamicStream(kDefaultPriority)); + if (stream) { + stream->set_visitor(this); + } + return stream; +} + +int QuicSpdyClientBase::GetNumSentClientHellosFromSession() { + return client_session()->GetNumSentClientHellos(); +} + +int QuicSpdyClientBase::GetNumReceivedServerConfigUpdatesFromSession() { + return client_session()->GetNumReceivedServerConfigUpdates(); +} + +void QuicSpdyClientBase::MaybeAddDataToResend(const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin) { + if (!FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support) { + return; + } + + if (client_session()->IsCryptoHandshakeConfirmed()) { + // The handshake is confirmed. No need to continue saving requests to + // resend. + data_to_resend_on_connect_.clear(); + return; + } + + // The handshake is not confirmed. Push the data onto the queue of data to + // resend if statelessly rejected. + std::unique_ptr<SpdyHeaderBlock> new_headers( + new SpdyHeaderBlock(headers.Clone())); + std::unique_ptr<QuicDataToResend> data_to_resend( + new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); + MaybeAddQuicDataToResend(std::move(data_to_resend)); +} + +void QuicSpdyClientBase::MaybeAddQuicDataToResend( + std::unique_ptr<QuicDataToResend> data_to_resend) { + data_to_resend_on_connect_.push_back(std::move(data_to_resend)); +} + +void QuicSpdyClientBase::ClearDataToResend() { + data_to_resend_on_connect_.clear(); +} + +void QuicSpdyClientBase::ResendSavedData() { + // Calling Resend will re-enqueue the data, so swap out + // data_to_resend_on_connect_ before iterating. + std::vector<std::unique_ptr<QuicDataToResend>> old_data; + old_data.swap(data_to_resend_on_connect_); + for (const auto& data : old_data) { + data->Resend(); + } +} + +void QuicSpdyClientBase::AddPromiseDataToResend(const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin) { + std::unique_ptr<SpdyHeaderBlock> new_headers( + new SpdyHeaderBlock(headers.Clone())); + push_promise_data_to_resend_.reset( + new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); +} + +bool QuicSpdyClientBase::CheckVary(const SpdyHeaderBlock& client_request, + const SpdyHeaderBlock& promise_request, + const SpdyHeaderBlock& promise_response) { + return true; +} + +void QuicSpdyClientBase::OnRendezvousResult(QuicSpdyStream* stream) { + std::unique_ptr<ClientQuicDataToResend> data_to_resend = + std::move(push_promise_data_to_resend_); + if (stream) { + stream->set_visitor(this); + stream->OnDataAvailable(); + } else if (data_to_resend.get()) { + data_to_resend->Resend(); + } +} + +size_t QuicSpdyClientBase::latest_response_code() const { + QUIC_BUG_IF(!store_response_) << "Response not stored!"; + return latest_response_code_; +} + +const string& QuicSpdyClientBase::latest_response_headers() const { + QUIC_BUG_IF(!store_response_) << "Response not stored!"; + return latest_response_headers_; +} + +const string& QuicSpdyClientBase::preliminary_response_headers() const { + QUIC_BUG_IF(!store_response_) << "Response not stored!"; + return preliminary_response_headers_; +} + +const SpdyHeaderBlock& QuicSpdyClientBase::latest_response_header_block() + const { + QUIC_BUG_IF(!store_response_) << "Response not stored!"; + return latest_response_header_block_; +} + +const string& QuicSpdyClientBase::latest_response_body() const { + QUIC_BUG_IF(!store_response_) << "Response not stored!"; + return latest_response_body_; +} + +const string& QuicSpdyClientBase::latest_response_trailers() const { + QUIC_BUG_IF(!store_response_) << "Response not stored!"; + return latest_response_trailers_; +} + +} // namespace net
diff --git a/net/tools/quic/quic_spdy_client_base.h b/net/tools/quic/quic_spdy_client_base.h new file mode 100644 index 0000000..76a2e92 --- /dev/null +++ b/net/tools/quic/quic_spdy_client_base.h
@@ -0,0 +1,215 @@ +// 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. +// +// A base class for the toy client, which connects to a specified port and sends +// QUIC request to that endpoint. + +#ifndef NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_BASE_H_ +#define NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_BASE_H_ + +#include <string> + +#include "base/macros.h" +#include "net/quic/core/crypto/crypto_handshake.h" +#include "net/quic/core/quic_client_push_promise_index.h" +#include "net/quic/core/quic_config.h" +#include "net/quic/platform/api/quic_socket_address.h" +#include "net/quic/platform/api/quic_string_piece.h" +#include "net/tools/quic/quic_client_base.h" +#include "net/tools/quic/quic_spdy_client_session.h" +#include "net/tools/quic/quic_spdy_client_stream.h" + +namespace net { + +class ProofVerifier; +class QuicServerId; + +class QuicSpdyClientBase : public QuicClientBase, + public QuicClientPushPromiseIndex::Delegate, + public QuicSpdyStream::Visitor { + public: + // A ResponseListener is notified when a complete response is received. + class ResponseListener { + public: + ResponseListener() {} + virtual ~ResponseListener() {} + virtual void OnCompleteResponse(QuicStreamId id, + const SpdyHeaderBlock& response_headers, + const std::string& response_body) = 0; + }; + + // The client uses these objects to keep track of any data to resend upon + // receipt of a stateless reject. Recall that the client API allows callers + // to optimistically send data to the server prior to handshake-confirmation. + // If the client subsequently receives a stateless reject, it must tear down + // its existing session, create a new session, and resend all previously sent + // data. It uses these objects to keep track of all the sent data, and to + // resend the data upon a subsequent connection. + class QuicDataToResend { + public: + // |headers| may be null, since it's possible to send data without headers. + QuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers, + QuicStringPiece body, + bool fin); + + virtual ~QuicDataToResend(); + + // Must be overridden by specific classes with the actual method for + // re-sending data. + virtual void Resend() = 0; + + protected: + std::unique_ptr<SpdyHeaderBlock> headers_; + QuicStringPiece body_; + bool fin_; + + private: + DISALLOW_COPY_AND_ASSIGN(QuicDataToResend); + }; + + QuicSpdyClientBase(const QuicServerId& server_id, + const QuicVersionVector& supported_versions, + const QuicConfig& config, + QuicConnectionHelperInterface* helper, + QuicAlarmFactory* alarm_factory, + std::unique_ptr<NetworkHelper> network_helper, + std::unique_ptr<ProofVerifier> proof_verifier); + + ~QuicSpdyClientBase() override; + + // QuicSpdyStream::Visitor + void OnClose(QuicSpdyStream* stream) override; + + // A spdy session has to call CryptoConnect on top of the regular + // initialization. + void InitializeSession() override; + + // Sends an HTTP request and does not wait for response before returning. + void SendRequest(const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin); + + // Sends an HTTP request and waits for response before returning. + void SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin); + + // Sends a request simple GET for each URL in |url_list|, and then waits for + // each to complete. + void SendRequestsAndWaitForResponse(const std::vector<std::string>& url_list); + + // Returns a newly created QuicSpdyClientStream. + QuicSpdyClientStream* CreateClientStream(); + + // Returns a the session used for this client downcasted to a + // QuicSpdyClientSession. + QuicSpdyClientSession* client_session(); + + QuicClientPushPromiseIndex* push_promise_index() { + return &push_promise_index_; + } + + bool CheckVary(const SpdyHeaderBlock& client_request, + const SpdyHeaderBlock& promise_request, + const SpdyHeaderBlock& promise_response) override; + void OnRendezvousResult(QuicSpdyStream*) override; + + // If the crypto handshake has not yet been confirmed, adds the data to the + // queue of data to resend if the client receives a stateless reject. + // Otherwise, deletes the data. + void MaybeAddQuicDataToResend( + std::unique_ptr<QuicDataToResend> data_to_resend); + + void set_store_response(bool val) { store_response_ = val; } + + size_t latest_response_code() const; + const std::string& latest_response_headers() const; + const std::string& preliminary_response_headers() const; + const SpdyHeaderBlock& latest_response_header_block() const; + const std::string& latest_response_body() const; + const std::string& latest_response_trailers() const; + + void set_response_listener(std::unique_ptr<ResponseListener> listener) { + response_listener_ = std::move(listener); + } + + protected: + int GetNumSentClientHellosFromSession() override; + int GetNumReceivedServerConfigUpdatesFromSession() override; + + // Takes ownership of |connection|. + std::unique_ptr<QuicSession> CreateQuicClientSession( + QuicConnection* connection) override; + + // If the crypto handshake has not yet been confirmed, adds the data to the + // queue of data to resend if the client receives a stateless reject. + // Otherwise, deletes the data. + void MaybeAddDataToResend(const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin); + + void ClearDataToResend() override; + + void ResendSavedData() override; + + void AddPromiseDataToResend(const SpdyHeaderBlock& headers, + QuicStringPiece body, + bool fin); + + private: + // Specific QuicClient class for storing data to resend. + class ClientQuicDataToResend : public QuicDataToResend { + public: + ClientQuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers, + QuicStringPiece body, + bool fin, + QuicSpdyClientBase* client) + : QuicDataToResend(std::move(headers), body, fin), client_(client) { + DCHECK(headers_); + DCHECK(client); + } + + ~ClientQuicDataToResend() override {} + + void Resend() override; + + private: + QuicSpdyClientBase* client_; + + DISALLOW_COPY_AND_ASSIGN(ClientQuicDataToResend); + }; + + // Index of pending promised streams. Must outlive |session_|. + QuicClientPushPromiseIndex push_promise_index_; + + // If true, store the latest response code, headers, and body. + bool store_response_; + // HTTP response code from most recent response. + int latest_response_code_; + // HTTP/2 headers from most recent response. + std::string latest_response_headers_; + // preliminary 100 Continue HTTP/2 headers from most recent response, if any. + std::string preliminary_response_headers_; + // HTTP/2 headers from most recent response. + SpdyHeaderBlock latest_response_header_block_; + // Body of most recent response. + std::string latest_response_body_; + // HTTP/2 trailers from most recent response. + std::string latest_response_trailers_; + + // Listens for full responses. + std::unique_ptr<ResponseListener> response_listener_; + + // Keeps track of any data that must be resent upon a subsequent successful + // connection, in case the client receives a stateless reject. + std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_; + + std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_; + + DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientBase); +}; + +} // namespace net + +#endif // NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_BASE_H_
diff --git a/net/tools/quic/quic_client_session.cc b/net/tools/quic/quic_spdy_client_session.cc similarity index 72% rename from net/tools/quic/quic_client_session.cc rename to net/tools/quic/quic_spdy_client_session.cc index a7408da..d13a84e 100644 --- a/net/tools/quic/quic_client_session.cc +++ b/net/tools/quic/quic_spdy_client_session.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 "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_spdy_client_session.h" #include "net/log/net_log_with_source.h" #include "net/quic/chromium/crypto/proof_verifier_chromium.h" @@ -18,30 +18,30 @@ namespace net { -QuicClientSession::QuicClientSession( +QuicSpdyClientSession::QuicSpdyClientSession( const QuicConfig& config, QuicConnection* connection, const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config, QuicClientPushPromiseIndex* push_promise_index) - : QuicClientSessionBase(connection, push_promise_index, config), + : QuicSpdyClientSessionBase(connection, push_promise_index, config), server_id_(server_id), crypto_config_(crypto_config) {} -QuicClientSession::~QuicClientSession() {} +QuicSpdyClientSession::~QuicSpdyClientSession() {} -void QuicClientSession::Initialize() { +void QuicSpdyClientSession::Initialize() { crypto_stream_ = CreateQuicCryptoStream(); - QuicClientSessionBase::Initialize(); + QuicSpdyClientSessionBase::Initialize(); } -void QuicClientSession::OnProofValid( +void QuicSpdyClientSession::OnProofValid( const QuicCryptoClientConfig::CachedState& /*cached*/) {} -void QuicClientSession::OnProofVerifyDetailsAvailable( +void QuicSpdyClientSession::OnProofVerifyDetailsAvailable( const ProofVerifyDetails& /*verify_details*/) {} -bool QuicClientSession::ShouldCreateOutgoingDynamicStream() { +bool QuicSpdyClientSession::ShouldCreateOutgoingDynamicStream() { DCHECK(!FLAGS_quic_reloadable_flag_quic_refactor_stream_creation); if (!crypto_stream_->encryption_established()) { QUIC_DLOG(INFO) << "Encryption not active so no outgoing stream created."; @@ -60,7 +60,7 @@ return true; } -QuicSpdyClientStream* QuicClientSession::CreateOutgoingDynamicStream( +QuicSpdyClientStream* QuicSpdyClientSession::CreateOutgoingDynamicStream( SpdyPriority priority) { if (!ShouldCreateOutgoingDynamicStream()) { return nullptr; @@ -72,32 +72,34 @@ return stream_ptr; } -std::unique_ptr<QuicSpdyClientStream> QuicClientSession::CreateClientStream() { +std::unique_ptr<QuicSpdyClientStream> +QuicSpdyClientSession::CreateClientStream() { return QuicMakeUnique<QuicSpdyClientStream>(GetNextOutgoingStreamId(), this); } -QuicCryptoClientStreamBase* QuicClientSession::GetMutableCryptoStream() { +QuicCryptoClientStreamBase* QuicSpdyClientSession::GetMutableCryptoStream() { return crypto_stream_.get(); } -const QuicCryptoClientStreamBase* QuicClientSession::GetCryptoStream() const { +const QuicCryptoClientStreamBase* QuicSpdyClientSession::GetCryptoStream() + const { return crypto_stream_.get(); } -void QuicClientSession::CryptoConnect() { +void QuicSpdyClientSession::CryptoConnect() { DCHECK(flow_controller()); crypto_stream_->CryptoConnect(); } -int QuicClientSession::GetNumSentClientHellos() const { +int QuicSpdyClientSession::GetNumSentClientHellos() const { return crypto_stream_->num_sent_client_hellos(); } -int QuicClientSession::GetNumReceivedServerConfigUpdates() const { +int QuicSpdyClientSession::GetNumReceivedServerConfigUpdates() const { return crypto_stream_->num_scup_messages_received(); } -bool QuicClientSession::ShouldCreateIncomingDynamicStream(QuicStreamId id) { +bool QuicSpdyClientSession::ShouldCreateIncomingDynamicStream(QuicStreamId id) { DCHECK(!FLAGS_quic_reloadable_flag_quic_refactor_stream_creation); if (!connection()->connected()) { QUIC_BUG << "ShouldCreateIncomingDynamicStream called when disconnected"; @@ -118,7 +120,7 @@ return true; } -QuicSpdyStream* QuicClientSession::CreateIncomingDynamicStream( +QuicSpdyStream* QuicSpdyClientSession::CreateIncomingDynamicStream( QuicStreamId id) { if (!ShouldCreateIncomingDynamicStream(id)) { return nullptr; @@ -130,23 +132,23 @@ } std::unique_ptr<QuicCryptoClientStreamBase> -QuicClientSession::CreateQuicCryptoStream() { +QuicSpdyClientSession::CreateQuicCryptoStream() { return QuicMakeUnique<QuicCryptoClientStream>( server_id_, this, new ProofVerifyContextChromium(0, NetLogWithSource()), crypto_config_, this); } -bool QuicClientSession::IsAuthorized(const string& authority) { +bool QuicSpdyClientSession::IsAuthorized(const string& authority) { return true; } -QuicSpdyClientStream* QuicClientSession::MaybeCreateOutgoingDynamicStream( +QuicSpdyClientStream* QuicSpdyClientSession::MaybeCreateOutgoingDynamicStream( SpdyPriority priority) { return static_cast<QuicSpdyClientStream*>( QuicSpdySession::MaybeCreateOutgoingDynamicStream(priority)); } -QuicSpdyStream* QuicClientSession::MaybeCreateIncomingDynamicStream( +QuicSpdyStream* QuicSpdyClientSession::MaybeCreateIncomingDynamicStream( QuicStreamId id) { QuicSpdyStream* stream = QuicSpdySession::MaybeCreateIncomingDynamicStream(id); @@ -157,7 +159,8 @@ return stream; } -std::unique_ptr<QuicStream> QuicClientSession::CreateStream(QuicStreamId id) { +std::unique_ptr<QuicStream> QuicSpdyClientSession::CreateStream( + QuicStreamId id) { return QuicMakeUnique<QuicSpdyClientStream>(id, this); }
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_spdy_client_session.h similarity index 79% rename from net/tools/quic/quic_client_session.h rename to net/tools/quic/quic_spdy_client_session.h index a7dc1804..1a252ac 100644 --- a/net/tools/quic/quic_client_session.h +++ b/net/tools/quic/quic_spdy_client_session.h
@@ -4,16 +4,16 @@ // // A client specific QuicSession subclass. -#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_SESSION_H_ -#define NET_TOOLS_QUIC_QUIC_CLIENT_SESSION_H_ +#ifndef NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_SESSION_H_ +#define NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_SESSION_H_ #include <memory> #include <string> #include "base/macros.h" -#include "net/quic/core/quic_client_session_base.h" #include "net/quic/core/quic_crypto_client_stream.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/core/quic_spdy_client_session_base.h" #include "net/tools/quic/quic_spdy_client_stream.h" namespace net { @@ -21,17 +21,17 @@ class QuicConnection; class QuicServerId; -class QuicClientSession : public QuicClientSessionBase { +class QuicSpdyClientSession : public QuicSpdyClientSessionBase { public: // Takes ownership of |connection|. Caller retains ownership of // |promised_by_url|. - QuicClientSession(const QuicConfig& config, - QuicConnection* connection, - const QuicServerId& server_id, - QuicCryptoClientConfig* crypto_config, - QuicClientPushPromiseIndex* push_promise_index); - ~QuicClientSession() override; - // Set up the QuicClientSession. Must be called prior to use. + QuicSpdyClientSession(const QuicConfig& config, + QuicConnection* connection, + const QuicServerId& server_id, + QuicCryptoClientConfig* crypto_config, + QuicClientPushPromiseIndex* push_promise_index); + ~QuicSpdyClientSession() override; + // Set up the QuicSpdyClientSession. Must be called prior to use. void Initialize() override; // QuicSession methods: @@ -44,7 +44,7 @@ bool IsAuthorized(const std::string& authority) override; - // QuicClientSessionBase methods: + // QuicSpdyClientSessionBase methods: void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; void OnProofVerifyDetailsAvailable( const ProofVerifyDetails& verify_details) override; @@ -89,9 +89,9 @@ QuicServerId server_id_; QuicCryptoClientConfig* crypto_config_; - DISALLOW_COPY_AND_ASSIGN(QuicClientSession); + DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientSession); }; } // namespace net -#endif // NET_TOOLS_QUIC_QUIC_CLIENT_SESSION_H_ +#endif // NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_SESSION_H_
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_spdy_client_session_test.cc similarity index 89% rename from net/tools/quic/quic_client_session_test.cc rename to net/tools/quic/quic_spdy_client_session_test.cc index 5b6cd71a..cba8935 100644 --- a/net/tools/quic/quic_client_session_test.cc +++ b/net/tools/quic/quic_spdy_client_session_test.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 "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_spdy_client_session.h" #include <vector> @@ -36,18 +36,19 @@ const char kServerHostname[] = "test.example.com"; const uint16_t kPort = 443; -class TestQuicClientSession : public QuicClientSession { +class TestQuicSpdyClientSession : public QuicSpdyClientSession { public: - explicit TestQuicClientSession(const QuicConfig& config, - QuicConnection* connection, - const QuicServerId& server_id, - QuicCryptoClientConfig* crypto_config, - QuicClientPushPromiseIndex* push_promise_index) - : QuicClientSession(config, - connection, - server_id, - crypto_config, - push_promise_index) {} + explicit TestQuicSpdyClientSession( + const QuicConfig& config, + QuicConnection* connection, + const QuicServerId& server_id, + QuicCryptoClientConfig* crypto_config, + QuicClientPushPromiseIndex* push_promise_index) + : QuicSpdyClientSession(config, + connection, + server_id, + crypto_config, + push_promise_index) {} std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override { return QuicMakeUnique<MockQuicSpdyClientStream>(GetNextOutgoingStreamId(), @@ -69,13 +70,13 @@ SpdyPriority priority) override { return FLAGS_quic_reloadable_flag_quic_refactor_stream_creation ? MaybeCreateOutgoingDynamicStream(priority) - : QuicClientSession::CreateOutgoingDynamicStream(priority); + : QuicSpdyClientSession::CreateOutgoingDynamicStream(priority); } }; -class QuicClientSessionTest : public QuicTestWithParam<QuicVersion> { +class QuicSpdyClientSessionTest : public QuicTestWithParam<QuicVersion> { protected: - QuicClientSessionTest() + QuicSpdyClientSessionTest() : crypto_config_(crypto_test_utils::ProofVerifierForTesting()), promised_stream_id_(kInvalidStreamId), associated_stream_id_(kInvalidStreamId) { @@ -84,7 +85,7 @@ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); } - ~QuicClientSessionTest() override { + ~QuicSpdyClientSessionTest() override { // Session must be destroyed before promised_by_url_ session_.reset(nullptr); } @@ -94,7 +95,7 @@ connection_ = new PacketSavingConnection(&helper_, &alarm_factory_, Perspective::IS_CLIENT, SupportedVersions(GetParam())); - session_.reset(new TestQuicClientSession( + session_.reset(new TestQuicSpdyClientSession( DefaultQuicConfig(), connection_, QuicServerId(kServerHostname, kPort, PRIVACY_MODE_DISABLED), &crypto_config_, &push_promise_index_)); @@ -130,7 +131,7 @@ MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; PacketSavingConnection* connection_; - std::unique_ptr<TestQuicClientSession> session_; + std::unique_ptr<TestQuicSpdyClientSession> session_; QuicClientPushPromiseIndex push_promise_index_; SpdyHeaderBlock push_promise_; string promise_url_; @@ -139,14 +140,14 @@ }; INSTANTIATE_TEST_CASE_P(Tests, - QuicClientSessionTest, + QuicSpdyClientSessionTest, ::testing::ValuesIn(AllSupportedVersions())); -TEST_P(QuicClientSessionTest, CryptoConnect) { +TEST_P(QuicSpdyClientSessionTest, CryptoConnect) { CompleteCryptoHandshake(); } -TEST_P(QuicClientSessionTest, NoEncryptionAfterInitialEncryption) { +TEST_P(QuicSpdyClientSessionTest, NoEncryptionAfterInitialEncryption) { // Complete a handshake in order to prime the crypto config for 0-RTT. CompleteCryptoHandshake(); @@ -192,7 +193,7 @@ EXPECT_EQ(0u, consumed.bytes_consumed); } -TEST_P(QuicClientSessionTest, MaxNumStreamsWithNoFinOrRst) { +TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) { EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber()); const uint32_t kServerMaxIncomingStreams = 1; @@ -212,7 +213,7 @@ EXPECT_FALSE(stream); } -TEST_P(QuicClientSessionTest, MaxNumStreamsWithRst) { +TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithRst) { EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber()); const uint32_t kServerMaxIncomingStreams = 1; @@ -233,7 +234,7 @@ EXPECT_NE(nullptr, stream); } -TEST_P(QuicClientSessionTest, ResetAndTrailers) { +TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) { // Tests the situation in which the client sends a RST at the same time that // the server sends trailing headers (trailers). Receipt of the trailers by // the client should result in all outstanding stream state being tidied up @@ -272,7 +273,7 @@ EXPECT_NE(nullptr, stream); } -TEST_P(QuicClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) { +TEST_P(QuicSpdyClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) { // Tests the situation where the client has sent a RST to the server, and has // received trailing headers with a malformed final byte offset value. CompleteCryptoHandshake(); @@ -298,7 +299,7 @@ session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers); } -TEST_P(QuicClientSessionTest, GoAwayReceived) { +TEST_P(QuicSpdyClientSessionTest, GoAwayReceived) { CompleteCryptoHandshake(); // After receiving a GoAway, I should no longer be able to create outgoing @@ -312,8 +313,9 @@ return framer->error() == QUIC_DECRYPTION_FAILURE; } -// Regression test for b/17206611. -TEST_P(QuicClientSessionTest, InvalidPacketReceived) { +// Various sorts of invalid packets that should not cause a connection +// to be closed. +TEST_P(QuicSpdyClientSessionTest, InvalidPacketReceived) { QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort); QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort); @@ -351,7 +353,7 @@ } // A packet with invalid framing should cause a connection to be closed. -TEST_P(QuicClientSessionTest, InvalidFramedPacketReceived) { +TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) { QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort); QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort); @@ -372,7 +374,7 @@ session_->ProcessUdpPacket(client_address, server_address, *received); } -TEST_P(QuicClientSessionTest, PushPromiseOnPromiseHeaders) { +TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeaders) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -384,7 +386,7 @@ QuicHeaderList()); } -TEST_P(QuicClientSessionTest, PushPromiseOnPromiseHeadersAlreadyClosed) { +TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeadersAlreadyClosed) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -398,7 +400,7 @@ QuicHeaderList()); } -TEST_P(QuicClientSessionTest, PushPromiseOutOfOrder) { +TEST_P(QuicSpdyClientSessionTest, PushPromiseOutOfOrder) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -418,7 +420,7 @@ QuicHeaderList()); } -TEST_P(QuicClientSessionTest, PushPromiseHandlePromise) { +TEST_P(QuicSpdyClientSessionTest, PushPromiseHandlePromise) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -431,7 +433,7 @@ EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); } -TEST_P(QuicClientSessionTest, PushPromiseAlreadyClosed) { +TEST_P(QuicSpdyClientSessionTest, PushPromiseAlreadyClosed) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -451,7 +453,7 @@ EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr); } -TEST_P(QuicClientSessionTest, PushPromiseDuplicateUrl) { +TEST_P(QuicSpdyClientSessionTest, PushPromiseDuplicateUrl) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -474,7 +476,7 @@ EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr); } -TEST_P(QuicClientSessionTest, ReceivingPromiseEnhanceYourCalm) { +TEST_P(QuicSpdyClientSessionTest, ReceivingPromiseEnhanceYourCalm) { for (size_t i = 0u; i < session_->get_max_promises(); i++) { push_promise_[":path"] = QuicStringPrintf("/bar%zu", i); @@ -502,7 +504,7 @@ EXPECT_EQ(session_->GetPromisedByUrl(promise_url), nullptr); } -TEST_P(QuicClientSessionTest, IsClosedTrueAfterResetPromisedAlreadyOpen) { +TEST_P(QuicSpdyClientSessionTest, IsClosedTrueAfterResetPromisedAlreadyOpen) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -513,7 +515,7 @@ EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_)); } -TEST_P(QuicClientSessionTest, IsClosedTrueAfterResetPromisedNonexistant) { +TEST_P(QuicSpdyClientSessionTest, IsClosedTrueAfterResetPromisedNonexistant) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); @@ -523,7 +525,7 @@ EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_)); } -TEST_P(QuicClientSessionTest, OnInitialHeadersCompleteIsPush) { +TEST_P(QuicSpdyClientSessionTest, OnInitialHeadersCompleteIsPush) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); session_->GetOrCreateStream(promised_stream_id_); @@ -536,14 +538,14 @@ session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock()); } -TEST_P(QuicClientSessionTest, OnInitialHeadersCompleteIsNotPush) { +TEST_P(QuicSpdyClientSessionTest, OnInitialHeadersCompleteIsNotPush) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); session_->CreateOutgoingDynamicStream(kDefaultPriority); session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock()); } -TEST_P(QuicClientSessionTest, DeletePromised) { +TEST_P(QuicSpdyClientSessionTest, DeletePromised) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); session_->GetOrCreateStream(promised_stream_id_); @@ -560,7 +562,7 @@ EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr); } -TEST_P(QuicClientSessionTest, ResetPromised) { +TEST_P(QuicSpdyClientSessionTest, ResetPromised) { // Initialize crypto before the client session will create a stream. CompleteCryptoHandshake(); session_->GetOrCreateStream(promised_stream_id_);
diff --git a/net/tools/quic/quic_spdy_client_stream.cc b/net/tools/quic/quic_spdy_client_stream.cc index b5b6044..664414a 100644 --- a/net/tools/quic/quic_spdy_client_stream.cc +++ b/net/tools/quic/quic_spdy_client_stream.cc
@@ -11,14 +11,14 @@ #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_logging.h" #include "net/spdy/core/spdy_protocol.h" -#include "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_spdy_client_session.h" using std::string; namespace net { QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id, - QuicClientSession* session) + QuicSpdyClientSession* session) : QuicSpdyStream(id, session), content_length_(-1), response_code_(0),
diff --git a/net/tools/quic/quic_spdy_client_stream.h b/net/tools/quic/quic_spdy_client_stream.h index 2bff0e4..606c2bbe 100644 --- a/net/tools/quic/quic_spdy_client_stream.h +++ b/net/tools/quic/quic_spdy_client_stream.h
@@ -17,13 +17,13 @@ namespace net { -class QuicClientSession; +class QuicSpdyClientSession; // All this does right now is send an SPDY request, and aggregate the // SPDY response. class QuicSpdyClientStream : public QuicSpdyStream { public: - QuicSpdyClientStream(QuicStreamId id, QuicClientSession* session); + QuicSpdyClientStream(QuicStreamId id, QuicSpdyClientSession* session); ~QuicSpdyClientStream() override; // Override the base class to parse and store headers. @@ -77,7 +77,7 @@ size_t header_bytes_read_; size_t header_bytes_written_; - QuicClientSession* session_; + QuicSpdyClientSession* session_; // These preliminary headers are used for the 100 Continue headers // that may arrive before the response headers when the request has
diff --git a/net/tools/quic/quic_spdy_client_stream_test.cc b/net/tools/quic/quic_spdy_client_stream_test.cc index bd78c145..3197db2f 100644 --- a/net/tools/quic/quic_spdy_client_stream_test.cc +++ b/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -16,7 +16,7 @@ #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/quic/test_tools/quic_test_utils.h" -#include "net/tools/quic/quic_client_session.h" +#include "net/tools/quic/quic_spdy_client_session.h" using base::IntToString; using std::string; @@ -28,25 +28,26 @@ namespace { -class MockQuicClientSession : public QuicClientSession { +class MockQuicSpdyClientSession : public QuicSpdyClientSession { public: - explicit MockQuicClientSession(QuicConnection* connection, - QuicClientPushPromiseIndex* push_promise_index) - : QuicClientSession( + explicit MockQuicSpdyClientSession( + QuicConnection* connection, + QuicClientPushPromiseIndex* push_promise_index) + : QuicSpdyClientSession( DefaultQuicConfig(), connection, QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED), &crypto_config_, push_promise_index), crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {} - ~MockQuicClientSession() override {} + ~MockQuicSpdyClientSession() override {} MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id)); private: QuicCryptoClientConfig crypto_config_; - DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession); + DISALLOW_COPY_AND_ASSIGN(MockQuicSpdyClientSession); }; class QuicSpdyClientStreamTest : public QuicTest { @@ -82,7 +83,7 @@ StrictMock<MockQuicConnection>* connection_; QuicClientPushPromiseIndex push_promise_index_; - MockQuicClientSession session_; + MockQuicSpdyClientSession session_; std::unique_ptr<QuicSpdyClientStream> stream_; std::unique_ptr<StreamVisitor> stream_visitor_; SpdyHeaderBlock headers_;
diff --git a/net/tools/quic/test_tools/quic_client_peer.cc b/net/tools/quic/test_tools/quic_client_peer.cc index 0f6d1ba..2936e77 100644 --- a/net/tools/quic/test_tools/quic_client_peer.cc +++ b/net/tools/quic/test_tools/quic_client_peer.cc
@@ -16,20 +16,19 @@ // static bool QuicClientPeer::CreateUDPSocketAndBind(QuicClient* client) { - return client->CreateUDPSocketAndBind(client->server_address(), - client->bind_to_address(), - client->local_port()); + return client->network_helper()->CreateUDPSocketAndBind( + client->server_address(), client->bind_to_address(), + client->local_port()); } // static void QuicClientPeer::CleanUpUDPSocket(QuicClient* client, int fd) { - client->CleanUpUDPSocket(fd); + client->epoll_network_helper()->CleanUpUDPSocket(fd); } // static void QuicClientPeer::SetClientPort(QuicClient* client, int port) { - client->fd_address_map_.back().second = - QuicSocketAddress(client->GetLatestClientAddress().host(), port); + client->epoll_network_helper()->SetClientPort(port); } // static
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index 4fa9146..2fa3f9e 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -30,7 +30,6 @@ using std::string; using testing::_; -using testing::Invoke; namespace net { namespace test { @@ -108,8 +107,59 @@ string common_name_; string cert_sct_; }; +} // namespace -} // anonymous namespace +class MockableQuicClientEpollNetworkHelper + : public QuicClientEpollNetworkHelper { + public: + using QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper; + ~MockableQuicClientEpollNetworkHelper() override {} + + void ProcessPacket(const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, + const QuicReceivedPacket& packet) override { + QuicClientEpollNetworkHelper::ProcessPacket(self_address, peer_address, + packet); + if (track_last_incoming_packet_) { + last_incoming_packet_ = packet.Clone(); + } + } + + QuicPacketWriter* CreateQuicPacketWriter() override { + QuicPacketWriter* writer = + QuicClientEpollNetworkHelper::CreateQuicPacketWriter(); + if (!test_writer_) { + return writer; + } + test_writer_->set_writer(writer); + return test_writer_; + } + + const QuicReceivedPacket* last_incoming_packet() { + return last_incoming_packet_.get(); + } + + void set_track_last_incoming_packet(bool track) { + track_last_incoming_packet_ = track; + } + + void UseWriter(QuicPacketWriterWrapper* writer) { + CHECK(test_writer_ == nullptr); + test_writer_ = writer; + } + + void set_peer_address(const QuicSocketAddress& address) { + CHECK(test_writer_ != nullptr); + test_writer_->set_peer_address(address); + } + + private: + QuicPacketWriterWrapper* test_writer_ = nullptr; + // The last incoming packet, iff |track_last_incoming_packet_| is true. + std::unique_ptr<QuicReceivedPacket> last_incoming_packet_; + // If true, copy each packet from ProcessPacket into |last_incoming_packet_| + bool track_last_incoming_packet_ = false; +}; MockableQuicClient::MockableQuicClient( QuicSocketAddress server_address, @@ -142,25 +192,17 @@ const QuicVersionVector& supported_versions, EpollServer* epoll_server, std::unique_ptr<ProofVerifier> proof_verifier) - : QuicClient(server_address, - server_id, - supported_versions, - config, - epoll_server, - QuicWrapUnique( - new RecordingProofVerifier(std::move(proof_verifier)))), - override_connection_id_(0), - test_writer_(nullptr), - track_last_incoming_packet_(false) {} - -void MockableQuicClient::ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) { - QuicClient::ProcessPacket(self_address, peer_address, packet); - if (track_last_incoming_packet_) { - last_incoming_packet_ = packet.Clone(); - } -} + : QuicClient( + server_address, + server_id, + supported_versions, + config, + epoll_server, + QuicMakeUnique<MockableQuicClientEpollNetworkHelper>(epoll_server, + this), + QuicWrapUnique( + new RecordingProofVerifier(std::move(proof_verifier)))), + override_connection_id_(0) {} MockableQuicClient::~MockableQuicClient() { if (connected()) { @@ -168,13 +210,16 @@ } } -QuicPacketWriter* MockableQuicClient::CreateQuicPacketWriter() { - QuicPacketWriter* writer = QuicClient::CreateQuicPacketWriter(); - if (!test_writer_) { - return writer; - } - test_writer_->set_writer(writer); - return test_writer_; +MockableQuicClientEpollNetworkHelper* +MockableQuicClient::mockable_network_helper() { + return static_cast<MockableQuicClientEpollNetworkHelper*>( + epoll_network_helper()); +} + +const MockableQuicClientEpollNetworkHelper* +MockableQuicClient::mockable_network_helper() const { + return static_cast<const MockableQuicClientEpollNetworkHelper*>( + epoll_network_helper()); } QuicConnectionId MockableQuicClient::GenerateNewConnectionId() { @@ -182,19 +227,24 @@ : QuicClient::GenerateNewConnectionId(); } -// Takes ownership of writer. -void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) { - CHECK(test_writer_ == nullptr); - test_writer_ = writer; -} - void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) { override_connection_id_ = connection_id; } +void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) { + mockable_network_helper()->UseWriter(writer); +} + void MockableQuicClient::set_peer_address(const QuicSocketAddress& address) { - CHECK(test_writer_ != nullptr); - test_writer_->set_peer_address(address); + mockable_network_helper()->set_peer_address(address); +} + +const QuicReceivedPacket* MockableQuicClient::last_incoming_packet() { + return mockable_network_helper()->last_incoming_packet(); +} + +void MockableQuicClient::set_track_last_incoming_packet(bool track) { + mockable_network_helper()->set_track_last_incoming_packet(track); } QuicTestClient::QuicTestClient(QuicSocketAddress server_address, @@ -329,7 +379,7 @@ if (headers) { new_headers.reset(new SpdyHeaderBlock(headers->Clone())); } - std::unique_ptr<QuicClientBase::QuicDataToResend> data_to_resend( + std::unique_ptr<QuicSpdyClientBase::QuicDataToResend> data_to_resend( new TestClientDataToResend(std::move(new_headers), body, fin, this, ack_listener)); client()->MaybeAddQuicDataToResend(std::move(data_to_resend)); @@ -502,7 +552,7 @@ } QuicSocketAddress QuicTestClient::local_address() const { - return client_->GetLatestClientAddress(); + return client_->network_helper()->GetLatestClientAddress(); } void QuicTestClient::ClearPerRequestState() {
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h index 26fca3c..cd9fa84 100644 --- a/net/tools/quic/test_tools/quic_test_client.h +++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -27,6 +27,8 @@ namespace test { +class MockableQuicClientEpollNetworkHelper; + // A quic client which allows mocking out reads and writes. class MockableQuicClient : public QuicClient { public: @@ -50,30 +52,23 @@ ~MockableQuicClient() override; - void ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) override; - - QuicPacketWriter* CreateQuicPacketWriter() override; QuicConnectionId GenerateNewConnectionId() override; - void UseWriter(QuicPacketWriterWrapper* writer); void UseConnectionId(QuicConnectionId connection_id); - const QuicReceivedPacket* last_incoming_packet() { - return last_incoming_packet_.get(); - } - void set_track_last_incoming_packet(bool track) { - track_last_incoming_packet_ = track; - } + + void UseWriter(QuicPacketWriterWrapper* writer); void set_peer_address(const QuicSocketAddress& address); + // The last incoming packet, iff |track_last_incoming_packet| is true. + const QuicReceivedPacket* last_incoming_packet(); + // If true, copy each packet from ProcessPacket into |last_incoming_packet| + void set_track_last_incoming_packet(bool track); + + // Casts the network helper to a MockableQuicClientEpollNetworkHelper. + MockableQuicClientEpollNetworkHelper* mockable_network_helper(); + const MockableQuicClientEpollNetworkHelper* mockable_network_helper() const; private: QuicConnectionId override_connection_id_; // ConnectionId to use, if nonzero - QuicPacketWriterWrapper* test_writer_; CachedNetworkParameters cached_network_paramaters_; - // The last incoming packet, iff |track_last_incoming_packet_| is true. - std::unique_ptr<QuicReceivedPacket> last_incoming_packet_; - // If true, copy each packet from ProcessPacket into |last_incoming_packet_| - bool track_last_incoming_packet_; DISALLOW_COPY_AND_ASSIGN(MockableQuicClient); };
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 061482d..7a0dd810 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -10904,6 +10904,1582 @@ } ] }, + "Out of Process Profiling Android": { + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "breakpad_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "cacheinvalidation_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "capture_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "cast_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "cc_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "chrome_public_test_apk" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "chrome_sync_shell_test_apk" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "components_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "content_shell_test_apk" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "crypto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "device_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "display_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "events_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "gcm_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "gfx_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "gl_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "gl_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "google_apis_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "gpu_ipc_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "jingle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "media_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "mojo_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "mojo_public_bindings_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "mojo_public_system_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "mojo_system_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "net_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "oop_heap_profiling_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "remoting_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "sandbox_linux_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "skia_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "sql_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "storage_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "ui_android_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "ui_touch_selection_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "1", + "device_type": "coho" + } + ] + }, + "test": "wtf_unittests" + } + ] + }, + "Out of Process Profiling Linux": { + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "accessibility_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "app_shell_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "aura_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 5 + }, + "test": "browser_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cacheinvalidation_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "capture_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cast_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cc_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chromedriver_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "compositor_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "crypto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "dbus_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "device_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "display_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "events_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gcm_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gfx_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "google_apis_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_ipc_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "interactive_ui_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "jingle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_public_bindings_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_public_system_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_system_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "nacl_helper_nonsfi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "nacl_loader_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "native_theme_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "net_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "oop_heap_profiling_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "pdf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ppapi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "printing_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "remoting_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sandbox_linux_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "skia_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sql_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "storage_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_touch_selection_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" + } + ] + }, + "Out of Process Profiling Mac": { + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "accessibility_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 5 + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 10 + }, + "test": "browser_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cacheinvalidation_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "capture_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cast_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cc_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chromedriver_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "crypto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "display_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gcm_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gfx_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "google_apis_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_ipc_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "interactive_ui_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "jingle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_public_bindings_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_public_system_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "mojo_system_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "native_theme_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "net_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "oop_heap_profiling_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "pdf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ppapi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "printing_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "remoting_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sandbox_mac_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "skia_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sql_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sync_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" + } + ], + "isolated_scripts": [ + { + "isolate_name": "telemetry_gpu_unittests", + "name": "telemetry_gpu_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "hard_timeout": 960, + "shards": 12 + } + }, + { + "isolate_name": "telemetry_unittests", + "name": "telemetry_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 2 + } + } + ] + }, + "Out of Process Profiling Windows": { + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 10 + }, + "test": "browser_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "cacheinvalidation_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "capture_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chrome_app_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "chrome_elf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "courgette_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "crypto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "device_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gcm_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "google_apis_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_ipc_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "installer_util_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "jingle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "media_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "native_theme_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "net_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "oop_heap_profiling_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "pdf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ppapi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "printing_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "remoting_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sbox_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sbox_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sbox_validation_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "setup_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "skia_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "sql_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "zucchini_unittests" + } + ] + }, "Ozone Linux": { "additional_compile_targets": [ "chrome"
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 71a4061..f0c0957 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -777,6 +777,10 @@ "label": "//chrome/installer/mini_installer:next_version_mini_installer", "type": "additional_compile_target", }, + "oop_heap_profiling_unit_tests": { + "label": "//chrome/profiling:unit_tests", + "type": "console_test_launcher", + }, "ozone_unittests": { "label": "//ui/ozone:ozone_unittests", "type": "console_test_launcher",
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 8962dcc6..b655dcd4 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -750,7 +750,7 @@ ], "experiments": [ { - "name": "DirectCompositionOverlays", + "name": "Enabled", "enable_features": [ "DirectCompositionOverlays" ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-basic-allow-preflight-cache-invalidation-by-header.htm b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-basic-allow-preflight-cache-invalidation-by-header.htm new file mode 100644 index 0000000..5a1e396 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-basic-allow-preflight-cache-invalidation-by-header.htm
@@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> + <head> + <title>Preflight cache should be invalidated in presence of custom header</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/get-host-info.sub.js"></script> + <script src="/common/utils.js"></script> + </head> + <body> + <script type="text/javascript"> + const uuid = token(); + const xhr = new XMLHttpRequest; + + async_test(function(test) { + xhr.onerror = test.unreached_func("FAIL: Network error."); + xhr.onload = test.step_func(function() { + // Token reset. We can start the test now. + assert_equals(xhr.responseText, "PASS"); + firstRequest(); + }); + + xhr.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/reset-token.py?token=" + uuid, true); + xhr.send(); + + function firstRequest() { + xhr.onload = test.step_func(function() { + assert_equals(xhr.responseText, "PASS: First PUT request."); + secondRequest(); + }); + xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py?token=" + uuid, true); + xhr.send(); + } + + function secondRequest() { + xhr.onload = test.step_func(function() { + assert_equals(xhr.responseText, "PASS: Second OPTIONS request was sent."); + test.done(); + }); + // Send a header not included in the inital cache. + xhr.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py?token=" + uuid, true); + xhr.setRequestHeader("x-test", "headerValue"); + xhr.send(); + } + }, "Preflight cache should be invalidated in presence of custom header"); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py new file mode 100644 index 0000000..6dc8a2a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-preflight-cache-invalidation.py
@@ -0,0 +1,47 @@ +def main(request, response): + def fail(message): + response.content = "FAIL " + request.method + ": " + str(message) + + def getState(token): + server_state = request.server.stash.take(token) + if not server_state: + return "Uninitialized" + return server_state + + def setState(state, token): + request.server.stash.put(token, state) + + response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin")) + response.headers.set("Access-Control-Allow-Credentials", "true") + token = request.GET.first("token", None) + state = getState(token) + + if state == "Uninitialized": + if request.method == "OPTIONS": + response.headers.set("Access-Control-Allow-Methods", "PUT") + response.headers.set("Access-Control-Max-Age", 10) + setState("OPTIONSSent", token) + else: + fail(state) + elif state == "OPTIONSSent": + if request.method == "PUT": + response.content = "PASS: First PUT request." + setState("FirstPUTSent", token) + else: + fail(state) + elif state == "FirstPUTSent": + if request.method == "OPTIONS": + response.headers.set("Access-Control-Allow-Methods", "PUT, XMETHOD") + response.headers.set("Access-Control-Allow-Headers", "x-test") + setState("SecondOPTIONSSent", token) + elif request.method == "PUT": + fail("Second PUT request sent without preflight") + else: + fail(state) + elif state == "SecondOPTIONSSent": + if request.method == "PUT" or request.method == "XMETHOD": + response.content = "PASS: Second OPTIONS request was sent." + else: + fail(state) + else: + fail(state)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/reset-token.py b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/reset-token.py new file mode 100644 index 0000000..5c9a577 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/reset-token.py
@@ -0,0 +1,5 @@ +def main(request, response): + response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin")) + token = request.GET["token"] + request.server.stash.put(token, "") + response.content = "PASS"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-update-event-updatewith-method.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-update-event-updatewith-method.https-expected.txt index 383d733..83bad4c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-update-event-updatewith-method.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-update-event-updatewith-method.https-expected.txt
@@ -1,8 +1,6 @@ This is a testharness.js-based test. FAIL Let target be the request which is dispatching the event. Failed to construct 'PaymentRequest': The provided value cannot be converted to a sequence. -FAIL Calling .updateWith() with an undispatched untrusted event throws "InvalidStateError" assert_throws: untrusted event of type "just a test" must throw "InvalidStateError" function "() => { - ev.updateWith(Promise.resolve()); - }" did not throw +PASS Calling .updateWith() with an undispatched untrusted event throws "InvalidStateError" FAIL Calling .updateWith() with a dispatched, untrusted event, throws "InvalidStateError" Failed to construct 'PaymentRequest': The provided value cannot be converted to a sequence. Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-basic-allow-preflight-cache-invalidation-by-header-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-basic-allow-preflight-cache-invalidation-by-header-expected.txt deleted file mode 100644 index f81335a3..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-basic-allow-preflight-cache-invalidation-by-header-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -PASS: First PUT request. -PASS: First request complete -PASS: Second OPTIONS request was sent. -PASS: Second request complete -
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-basic-allow-preflight-cache-invalidation-by-header.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-basic-allow-preflight-cache-invalidation-by-header.html deleted file mode 100644 index d9dbf1f..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-basic-allow-preflight-cache-invalidation-by-header.html +++ /dev/null
@@ -1,74 +0,0 @@ -<html> -<body> -<pre id='console'></pre> -<script type="text/javascript"> -function log(message) -{ - document.getElementById('console').appendChild(document.createTextNode(message + "\n")); -} - -if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.waitUntilDone(); -} - -function errorHandler(event) -{ - log("FAIL: Network error. "); - if (window.testRunner) - testRunner.notifyDone(); -} - -var filename = "filename=preflightCacheInvalidationByHeader.txt"; - -var xhr = new XMLHttpRequest; -xhr.onerror = errorHandler; - -start = function() -{ - // Temp file removed. We can start the test now. - if (xhr.readyState == xhr.DONE) { - firstRequest(); - } -} - -xhr.open("GET", "/resources/reset-temp-file.php?" + filename, true); -xhr.onreadystatechange = start; -xhr.send(); - -function firstRequest() -{ - xhr.onreadystatechange = function() - { - if (xhr.readyState == xhr.DONE) { - log(xhr.responseText); - log("PASS: First request complete"); - secondRequest(); - } - } - - xhr.open("PUT", "http://localhost:8000/xmlhttprequest/resources/access-control-basic-preflight-cache-invalidation.php?" + filename, true); - xhr.send(); -} - -function secondRequest() -{ - xhr.onreadystatechange = function() - { - if (xhr.readyState == xhr.DONE) { - log(xhr.responseText); - log("PASS: Second request complete"); - if (window.testRunner) - testRunner.notifyDone(); - } - } - - // Send a header not included in the inital cache. - xhr.open("PUT", "http://localhost:8000/xmlhttprequest/resources/access-control-basic-preflight-cache-invalidation.php?" + filename, true); - xhr.setRequestHeader("x-webkit-test", "headerValue"); - xhr.send(); -} - -</script> -</body> -</html>
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp index ec83afe..8108d34 100644 --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -779,8 +779,8 @@ pts, colors, nullptr, ARRAY_SIZE(colors), SkShader::kClamp_TileMode)); PaintRecorder recorder; recorder.beginRecording(kMarkerWidth, kMarkerHeight); - recorder.getRecordingCanvas()->drawCircle(kR, kR, kR, flags); - + recorder.getRecordingCanvas()->drawOval(SkRect::MakeWH(2 * kR, 2 * kR), + flags); return recorder.finishRecordingAsPicture(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css b/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css index ffc732d..4675fca 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css +++ b/third_party/WebKit/Source/devtools/front_end/elements/stylesSidebarPane.css
@@ -145,6 +145,10 @@ .styles-sidebar-pane-toolbar-container { flex-shrink: 0; overflow: hidden; + position: sticky; + top: 0; + background-color: #fff; + z-index: 1; } .styles-sidebar-pane-toolbar { @@ -196,6 +200,7 @@ bottom: 0; visibility: hidden; background-color: rgba(255, 255, 255, 0.9); + z-index: 0; } .styles-pane:not(.is-editing-style) .styles-section.matched-styles:not(.read-only):hover .sidebar-pane-section-toolbar {
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEvent.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEvent.cpp index 109ecb6..12d9b03 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEvent.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEvent.cpp
@@ -104,16 +104,16 @@ void PaymentRequestUpdateEvent::updateWith(ScriptState* script_state, ScriptPromise promise, ExceptionState& exception_state) { - if (!updater_) - return; - - if (!IsBeingDispatched()) { + if (!isTrusted()) { exception_state.ThrowDOMException( kInvalidStateError, - "Cannot update details when the event is not being dispatched"); + "Cannot update details when the event is not trusted"); return; } + if (!updater_) + return; + if (wait_for_update_) { exception_state.ThrowDOMException(kInvalidStateError, "Cannot update details twice");
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp index f65812d..852d11c9 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequestUpdateEventTest.cpp
@@ -40,6 +40,7 @@ PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingaddresschange); MockPaymentUpdater* updater = new MockPaymentUpdater; + event->SetTrusted(true); event->SetPaymentDetailsUpdater(updater); event->SetEventPhase(Event::kCapturingPhase); ScriptPromiseResolver* payment_details = @@ -59,6 +60,7 @@ PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingaddresschange); MockPaymentUpdater* updater = new MockPaymentUpdater; + event->SetTrusted(true); event->SetPaymentDetailsUpdater(updater); event->SetEventPhase(Event::kCapturingPhase); ScriptPromiseResolver* payment_details = @@ -92,6 +94,7 @@ PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingaddresschange); MockPaymentUpdater* updater = new MockPaymentUpdater; + event->SetTrusted(true); event->SetPaymentDetailsUpdater(updater); event->SetEventPhase(Event::kCapturingPhase); event->updateWith( @@ -112,6 +115,7 @@ V8TestingScope scope; PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingaddresschange); + event->SetTrusted(true); event->updateWith( scope.GetScriptState(), @@ -131,6 +135,7 @@ PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingaddresschange); event->SetPaymentDetailsUpdater(request); + event->SetTrusted(true); EXPECT_FALSE(scope.GetExceptionState().HadException()); String error_message; @@ -162,6 +167,7 @@ BuildPaymentDetailsInitForTest(), scope.GetExceptionState()); PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingoptionchange); + event->SetTrusted(true); event->SetPaymentDetailsUpdater(request); EXPECT_FALSE(scope.GetExceptionState().HadException()); @@ -195,6 +201,7 @@ EXPECT_FALSE(scope.GetExceptionState().HadException()); PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingaddresschange); + event->SetTrusted(true); event->SetPaymentDetailsUpdater(request); event->SetEventPhase(Event::kCapturingPhase); ScriptPromiseResolver* payment_details = @@ -227,6 +234,7 @@ EXPECT_FALSE(scope.GetExceptionState().HadException()); PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( scope.GetExecutionContext(), EventTypeNames::shippingoptionchange); + event->SetTrusted(true); event->SetPaymentDetailsUpdater(request); event->SetEventPhase(Event::kCapturingPhase); ScriptPromiseResolver* payment_details = @@ -249,5 +257,19 @@ payment_details->Resolve("foo"); } +TEST(PaymentRequestUpdateEventTest, NotAllowUntrustedEvent) { + V8TestingScope scope; + PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create( + scope.GetExecutionContext(), EventTypeNames::shippingaddresschange); + event->SetTrusted(false); + + event->updateWith( + scope.GetScriptState(), + ScriptPromiseResolver::Create(scope.GetScriptState())->Promise(), + scope.GetExceptionState()); + + EXPECT_TRUE(scope.GetExceptionState().HadException()); +} + } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc b/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc index bf3678e..a04801c5 100644 --- a/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc +++ b/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc
@@ -21,7 +21,7 @@ base::trace_event::ProcessMemoryDump* memory_dump) { using base::trace_event::MemoryAllocatorDump; #define DUMP_COUNTER(CounterType) \ - memory_dump->CreateAllocatorDump("counter/" #CounterType) \ + memory_dump->CreateAllocatorDump("blink_objects/" #CounterType) \ ->AddScalar("object_count", MemoryAllocatorDump::kUnitsObjects, \ InstanceCounters::CounterValue( \ InstanceCounters::k##CounterType##Counter));
diff --git a/third_party/WebKit/Source/platform/graphics/test/MockPaintCanvas.h b/third_party/WebKit/Source/platform/graphics/test/MockPaintCanvas.h index c386128..3776ba9a1 100644 --- a/third_party/WebKit/Source/platform/graphics/test/MockPaintCanvas.h +++ b/third_party/WebKit/Source/platform/graphics/test/MockPaintCanvas.h
@@ -59,9 +59,6 @@ void(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags)); - MOCK_METHOD4( - drawCircle, - void(SkScalar cx, SkScalar cy, SkScalar radius, const PaintFlags& flags)); MOCK_METHOD5(drawArc, void(const SkRect& oval, SkScalar start_angle,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc index ed5e756..a5ddef26 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -27,6 +27,7 @@ #include "platform/scheduler/renderer/web_view_scheduler_impl.h" #include "platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h" #include "public/platform/Platform.h" +#include "public/platform/scheduler/renderer_process_type.h" namespace blink { namespace scheduler { @@ -165,7 +166,9 @@ #define TASK_DURATION_METRIC_NAME "RendererScheduler.TaskDurationPerQueueType2" #define TASK_COUNT_METRIC_NAME "RendererScheduler.TaskCountPerQueueType" -#define MAIN_THREAD_LOAD_METRIC_NAME "RendererScheduler.RendererMainThreadLoad4" +#define MAIN_THREAD_LOAD_METRIC_NAME "RendererScheduler.RendererMainThreadLoad5" +#define EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME \ + MAIN_THREAD_LOAD_METRIC_NAME ".Extension" RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( RendererSchedulerImpl* renderer_scheduler_impl, @@ -252,7 +255,8 @@ hidden_task_duration_reporter(TASK_DURATION_METRIC_NAME ".Hidden"), visible_task_duration_reporter(TASK_DURATION_METRIC_NAME ".Visible"), hidden_music_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".HiddenMusic") { + ".HiddenMusic"), + process_type(RendererProcessType::kRenderer) { main_thread_load_tracker.Resume(now); foreground_main_thread_load_tracker.Resume(now); } @@ -1863,6 +1867,10 @@ return main_thread_seems_unresponsive; } +void RendererSchedulerImpl::SetRendererProcessType(RendererProcessType type) { + main_thread_only().process_type = type; +} + void RendererSchedulerImpl::RegisterTimeDomain(TimeDomain* time_domain) { helper_.RegisterTimeDomain(time_domain); } @@ -2157,6 +2165,13 @@ DCHECK_LE(load_percentage, 100); UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME, load_percentage); + + if (main_thread_only().process_type == + RendererProcessType::kExtensionRenderer) { + UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME, + load_percentage); + } + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler.RendererMainThreadLoad", load_percentage); } @@ -2167,14 +2182,23 @@ int load_percentage = static_cast<int>(load * 100); DCHECK_LE(load_percentage, 100); - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Foreground", - load_percentage); + switch (main_thread_only().process_type) { + case RendererProcessType::kExtensionRenderer: + UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME + ".Foreground", + load_percentage); + break; + case RendererProcessType::kRenderer: + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Foreground", + load_percentage); - if (time - main_thread_only().background_status_changed_at > - base::TimeDelta::FromMinutes(1)) { - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME - ".Foreground.AfterFirstMinute", - load_percentage); + if (time - main_thread_only().background_status_changed_at > + base::TimeDelta::FromMinutes(1)) { + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME + ".Foreground.AfterFirstMinute", + load_percentage); + } + break; } TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), @@ -2188,14 +2212,23 @@ int load_percentage = static_cast<int>(load * 100); DCHECK_LE(load_percentage, 100); - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Background", - load_percentage); + switch (main_thread_only().process_type) { + case RendererProcessType::kExtensionRenderer: + UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME + ".Background", + load_percentage); + break; + case RendererProcessType::kRenderer: + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Background", + load_percentage); - if (time - main_thread_only().background_status_changed_at > - base::TimeDelta::FromMinutes(1)) { - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME - ".Background.AfterFirstMinute", - load_percentage); + if (time - main_thread_only().background_status_changed_at > + base::TimeDelta::FromMinutes(1)) { + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME + ".Background.AfterFirstMinute", + load_percentage); + } + break; } TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h index 599847a..d314ef9 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -127,6 +127,7 @@ void SetRAILModeObserver(RAILModeObserver* observer) override; bool MainThreadSeemsUnresponsive( base::TimeDelta main_thread_responsiveness_threshold) override; + void SetRendererProcessType(RendererProcessType type) override; // RenderWidgetSignals::Observer implementation: void SetAllRenderWidgetsHidden(bool hidden) override; @@ -619,6 +620,7 @@ TaskDurationMetricReporter hidden_task_duration_reporter; TaskDurationMetricReporter visible_task_duration_reporter; TaskDurationMetricReporter hidden_music_task_duration_reporter; + RendererProcessType process_type; }; struct AnyThread {
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc index 4fbe36f..8e7b6527 100644 --- a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc +++ b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
@@ -125,5 +125,7 @@ return false; } +void FakeRendererScheduler::SetRendererProcessType(RendererProcessType type) {} + } // namespace scheduler } // namespace blink
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index ff35a751..14bf01b 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -458,6 +458,7 @@ "platform/scheduler/child/webthread_base.h", "platform/scheduler/renderer/render_widget_scheduling_state.h", "platform/scheduler/renderer/renderer_scheduler.h", + "platform/scheduler/renderer_process_type.h", "web/WebAXEnums.h", "web/WebAXObject.h", "web/WebActiveWheelFlingParameters.h",
diff --git a/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h index 8b8e92e..9197280 100644 --- a/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h +++ b/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h
@@ -36,6 +36,7 @@ namespace blink { namespace scheduler { +enum class RendererProcessType; class RenderWidgetSchedulingState; class BLINK_PLATFORM_EXPORT RendererScheduler : public ChildScheduler { @@ -198,6 +199,10 @@ virtual bool MainThreadSeemsUnresponsive( base::TimeDelta main_thread_responsiveness_threshold) = 0; + // Sets the kind of renderer process. Should be called on the main thread + // once. + virtual void SetRendererProcessType(RendererProcessType type) = 0; + protected: RendererScheduler(); DISALLOW_COPY_AND_ASSIGN(RendererScheduler);
diff --git a/third_party/WebKit/public/platform/scheduler/renderer_process_type.h b/third_party/WebKit/public/platform/scheduler/renderer_process_type.h new file mode 100644 index 0000000..23a1db4 --- /dev/null +++ b/third_party/WebKit/public/platform/scheduler/renderer_process_type.h
@@ -0,0 +1,19 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_RENDERER_PROCESS_TYPE_H_ +#define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_RENDERER_PROCESS_TYPE_H_ + +namespace blink { +namespace scheduler { + +enum class RendererProcessType { + kExtensionRenderer, + kRenderer, +}; + +} // namespace scheduler +} // namespace blink + +#endif // THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_RENDERER_PROCESS_TYPE_H_
diff --git a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h index a85be16..ce3a646 100644 --- a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h +++ b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
@@ -61,6 +61,7 @@ void SetRAILModeObserver(RAILModeObserver* observer) override; bool MainThreadSeemsUnresponsive( base::TimeDelta main_thread_responsiveness_threshold) override; + void SetRendererProcessType(RendererProcessType type) override; private: DISALLOW_COPY_AND_ASSIGN(FakeRendererScheduler);
diff --git a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h index 814d5ff..8dd05d0 100644 --- a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h +++ b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
@@ -64,6 +64,7 @@ MOCK_METHOD1(SetTopLevelBlameContext, void(base::trace_event::BlameContext*)); MOCK_METHOD1(SetRAILModeObserver, void(RAILModeObserver*)); MOCK_METHOD1(MainThreadSeemsUnresponsive, bool(base::TimeDelta)); + MOCK_METHOD1(SetRendererProcessType, void(RendererProcessType)); private: DISALLOW_COPY_AND_ASSIGN(MockRendererScheduler);
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index 1b4b9c95..22725ab 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -90,9 +90,6 @@ "chrome/browser/resources/invalidations_resources.grd": { "includes": [11910], }, - "chrome/browser/resources/md_policy/policy_resources.grd": { - "structures": [11920], - }, "chrome/browser/resources/net_internals_resources.grd": { "includes": [11960], },
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 039bdd5..71125b82 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -207,6 +207,10 @@ 'Mojo Linux': 'release_trybot', 'Mojo Windows': 'release_bot_x86_minimal_symbols', 'Ozone Linux': 'ozone_linux_release_bot', + 'Out of Process Profiling Android': 'release_bot_out_of_process_profiling', + 'Out of Process Profiling Linux': 'release_bot_out_of_process_profiling', + 'Out of Process Profiling Mac': 'release_bot_out_of_process_profiling', + 'Out of Process Profiling Windows': 'release_bot_out_of_process_profiling', 'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64', 'Site Isolation Linux': 'release_trybot', 'Site Isolation Win': 'release_trybot_x86', @@ -1442,6 +1446,10 @@ 'release_bot', 'mac_strip', ], + 'release_bot_out_of_process_profiling': [ + 'release_bot', 'out_of_process_profiling', + ], + 'release_bot_x86': [ 'release_bot', 'x86', ], @@ -1873,6 +1881,10 @@ 'gn_args': 'optimize_for_fuzzing=true', }, + 'out_of_process_profiling': { + 'gn_args': 'enable_oop_heap_profiling=true', + }, + 'ozone_linux': { 'gn_args': ('ozone_auto_platforms=false ozone_platform_wayland=true ' 'ozone_platform="x11" '
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b8274150..ec1ccb6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -20870,9 +20870,10 @@ </enum> <enum name="InstantTethering_HostScanResult"> - <int value="0" label="Notification not shown"/> + <int value="0" label="No hosts found"/> <int value="1" label="Notification shown for single host"/> <int value="2" label="Notification shown for multiple hosts"/> + <int value="3" label="Hosts found but no notification shown"/> </enum> <enum name="IntelMaxMicroArchitecture">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 5799cad8..b7343102 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -27426,15 +27426,14 @@ enum="InstantTethering_HostScanResult"> <owner>hansberry@chromium.com</owner> <summary> - Provides a breakdown of the results of each host scan. The result can be 1) - no notification shown (no hosts found), 2) a notification was shown for a - single available host, or 3) a notification was shown for multiple available - hosts. This metric is recorded after each host scan. + Provides a breakdown of the results of each host scan. This metric is + recorded after each host scan. - Comparing 1) against the sum of 2) and 3) can help determine the success - rate of host scans. + Comparing the number of times no hosts were found against the other buckets + can help determine how often a host scan is useful. - The sum of 2) and 3) can be used as a baseline of comparison against + The sum of the buckets capturing that a notification was shown can be used + as a baseline of comparison against InstantTethering.ConnectionToHostResult.ProvisioningFailureRate to roughly measure engagement with the notification. </summary> @@ -63657,6 +63656,23 @@ </histogram> <histogram name="RendererScheduler.RendererMainThreadLoad4" units="%"> + <obsolete> + Replaced with RendererMainThreadLoad5 as of August 2017. + </obsolete> + <owner>altimin@chromium.org</owner> + <summary> + Renderer main thread load (percentage of time spent in tasks), reported in + one second chunks. + + See http://bit.ly/chromium-renderer-main-thread-load-metric for details. + + This metric is emitted when the renderer main thread task is completed or + renderer is backgrounded or foregrounded, at most once per second per + renderer amortized. + </summary> +</histogram> + +<histogram name="RendererScheduler.RendererMainThreadLoad5" units="%"> <owner>altimin@chromium.org</owner> <summary> Renderer main thread load (percentage of time spent in tasks), reported in @@ -98564,19 +98580,28 @@ </histogram_suffixes> <histogram_suffixes name="RendererScheduler.MainThreadLoadSplit" separator="."> + <suffix name="Extension" label="This only includes extension renderers"/> <suffix name="Background" - label="Main thread load when the renderer is backgrounded."/> + label="Main thread load when the renderer is backgrounded. This does + not include extension renderers."/> + <suffix name="Extension.Background" + label="Main thread load when the renderer is backgrounded. This only + includes extension renderers."/> <suffix name="Background.AfterFirstMinute" label="Main thread load when the renderer is backgrounded for longer than one minute. Most of loading tasks are expected to complete - by then."/> + by then. This does not include extension renderers."/> <suffix name="Foreground" - label="Main thread load when the renderer is foregrounded."/> + label="Main thread load when the renderer is foregrounded. This does + not include extension renderers."/> + <suffix name="Extension.Foreground" + label="Main thread load when the renderer is foregrounded. This only + includes extension renderers."/> <suffix name="Foreground.AfterFirstMinute" label="Main thread load when the renderer is foregrounded for longer than one minute. Most of loading tasks are expected to complete - by then."/> - <affected-histogram name="RendererScheduler.RendererMainThreadLoad4"/> + by then. This does not include extension renderers."/> + <affected-histogram name="RendererScheduler.RendererMainThreadLoad5"/> </histogram_suffixes> <histogram_suffixes name="RendererScheduler.TaskCountPerTaskLength"
diff --git a/ui/app_list/folder_image.cc b/ui/app_list/folder_image.cc index 47513c8..1d5bb67 100644 --- a/ui/app_list/folder_image.cc +++ b/ui/app_list/folder_image.cc
@@ -85,8 +85,7 @@ flags.setStyle(cc::PaintFlags::kFill_Style); flags.setAntiAlias(true); flags.setColor(kFolderBubbleColor); - canvas->sk_canvas()->drawCircle(bubble_center.x(), bubble_center.y(), - kFolderBubbleRadius, flags); + canvas->DrawCircle(bubble_center, kFolderBubbleRadius, flags); if (icons_.size() == 0) return;
diff --git a/ui/aura/test/env_test_helper.h b/ui/aura/test/env_test_helper.h index 4ea5020..5bc59d3 100644 --- a/ui/aura/test/env_test_helper.h +++ b/ui/aura/test/env_test_helper.h
@@ -45,6 +45,9 @@ env_->in_mus_shutdown_ = window_tree_client ? false : true; } + // Use to force Env::last_mouse_location() to return the value last set. + // This matters for MUS, which may not return the last explicitly set + // location. void SetAlwaysUseLastMouseLocation(bool value) { env_->always_use_last_mouse_location_ = value; }
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_basketball.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_basketball.png new file mode 100644 index 0000000..7001045 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_basketball.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_bike.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_bike.png new file mode 100644 index 0000000..610ec76 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_bike.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_bird.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_bird.png new file mode 100644 index 0000000..06d3c11f --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_bird.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_cheese.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_cheese.png new file mode 100644 index 0000000..6f441e6 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_cheese.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_football.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_football.png new file mode 100644 index 0000000..bc031488 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_football.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_ramen.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_ramen.png new file mode 100644 index 0000000..ef3aff8 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_ramen.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_sunglasses.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_sunglasses.png new file mode 100644 index 0000000..376eacd1 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_sunglasses.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_sushi.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_sushi.png new file mode 100644 index 0000000..c7a542da --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_sushi.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_tamagochi.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_tamagochi.png new file mode 100644 index 0000000..0aca2c2 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_tamagochi.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_vinyl.png b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_vinyl.png new file mode 100644 index 0000000..30f0ee10d --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/illustration/avatar_vinyl.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_basketball.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_basketball.png new file mode 100644 index 0000000..0488a6a --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_basketball.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_bike.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_bike.png new file mode 100644 index 0000000..335f65c --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_bike.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_bird.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_bird.png new file mode 100644 index 0000000..d1062ed --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_bird.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_cheese.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_cheese.png new file mode 100644 index 0000000..d86028c --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_cheese.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_football.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_football.png new file mode 100644 index 0000000..732284f --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_football.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_ramen.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_ramen.png new file mode 100644 index 0000000..4d81939 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_ramen.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_sunglasses.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_sunglasses.png new file mode 100644 index 0000000..f059077 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_sunglasses.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_sushi.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_sushi.png new file mode 100644 index 0000000..250bbc4 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_sushi.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_tamagochi.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_tamagochi.png new file mode 100644 index 0000000..ae633fe --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_tamagochi.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_vinyl.png b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_vinyl.png new file mode 100644 index 0000000..8f483de12 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/illustration/avatar_vinyl.png Binary files differ
diff --git a/ui/chromeos/resources/ui_chromeos_resources.grd b/ui/chromeos/resources/ui_chromeos_resources.grd index b84066d0..d458dea 100644 --- a/ui/chromeos/resources/ui_chromeos_resources.grd +++ b/ui/chromeos/resources/ui_chromeos_resources.grd
@@ -68,6 +68,16 @@ <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_45" file="default_user_images/origami/avatar_panda.png" /> <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_46" file="default_user_images/origami/avatar_unicorn.png" /> <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_47" file="default_user_images/origami/avatar_butterflies.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_48" file="default_user_images/illustration/avatar_bird.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_49" file="default_user_images/illustration/avatar_ramen.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_50" file="default_user_images/illustration/avatar_tamagochi.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_51" file="default_user_images/illustration/avatar_cheese.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_52" file="default_user_images/illustration/avatar_football.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_53" file="default_user_images/illustration/avatar_basketball.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_54" file="default_user_images/illustration/avatar_vinyl.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_55" file="default_user_images/illustration/avatar_sushi.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_56" file="default_user_images/illustration/avatar_bike.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_57" file="default_user_images/illustration/avatar_sunglasses.png" /> <!-- Print Job Notification images. --> <structure type="chrome_scaled_image" name="IDR_PRINT_NOTIFICATION_CANCEL" file="print_notification/cancel.png" />
diff --git a/ui/chromeos/ui_chromeos_strings.grd b/ui/chromeos/ui_chromeos_strings.grd index 6a0cf7e..1ff7211 100644 --- a/ui/chromeos/ui_chromeos_strings.grd +++ b/ui/chromeos/ui_chromeos_strings.grd
@@ -209,6 +209,36 @@ <message name="IDS_LOGIN_DEFAULT_USER_DESC_47" desc="Description of the default user icon with a picture of butterflies"> Butterflies </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_48" desc="Description of the default user icon with a picture of a bird"> + Bird + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_49" desc="Description of the default user icon with a picture of ramen"> + Ramen + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_50" desc="Description of the default user icon with a picture of a tamagochi"> + Tamagochi + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_51" desc="Description of the default user icon with a picture of a cheese"> + Cheese + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_52" desc="Description of the default user icon with a picture of a football"> + Football + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_53" desc="Description of the default user icon with a picture of a basketball"> + Basketball + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_54" desc="Description of the default user icon with a picture of a vinyl"> + Vinyl + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_55" desc="Description of the default user icon with a picture of sushi"> + Sushi + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_56" desc="Description of the default user icon with a picture of a bike"> + Bike + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_57" desc="Description of the default user icon with a picture of a pair of sunglasses"> + Sunglasses + </message> <!-- Attribution strings for stock user images, not translateable. --> <message translateable="false" name="IDS_LOGIN_DEFAULT_USER_AUTHOR">
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index 9e190b6..a551486 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -989,7 +989,6 @@ const float vx = gesture_event.data.fling_start.velocity_x; const float vy = gesture_event.data.fling_start.velocity_y; current_fling_velocity_ = gfx::Vector2dF(vx, vy); - DCHECK(!current_fling_velocity_.IsZero()); fling_curve_ = client_->CreateFlingAnimationCurve( gesture_event.source_device, WebFloatPoint(vx, vy), blink::WebSize()); disallow_horizontal_fling_scroll_ = !vx;
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.cc b/ui/events/gestures/blink/web_gesture_curve_impl.cc index 4febdaf..a9901956 100644 --- a/ui/events/gestures/blink/web_gesture_curve_impl.cc +++ b/ui/events/gestures/blink/web_gesture_curve_impl.cc
@@ -32,7 +32,6 @@ std::unique_ptr<GestureCurve> CreateDefaultPlatformCurve( blink::WebGestureDevice device_source, const gfx::Vector2dF& initial_velocity) { - DCHECK(!initial_velocity.IsZero()); if (device_source == blink::kWebGestureDeviceSyntheticAutoscroll) { return base::MakeUnique<FixedVelocityCurve>(initial_velocity, base::TimeTicks());
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 877a2ba..3e49b15 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -330,8 +330,7 @@ sources -= [ "canvas_notimplemented.cc" ] } - # Desktop and Android+VR only. - if (use_aura || (!is_ios && !is_android) || (is_android && enable_vr)) { + if (!is_ios) { sources += [ "paint_vector_icon.cc", "paint_vector_icon.h", @@ -710,11 +709,12 @@ ] } + if (!is_ios) { + sources += [ "paint_vector_icon_unittest.cc" ] + } + if (!is_android && !is_ios) { - sources += [ - "paint_vector_icon_unittest.cc", - "render_text_unittest.cc", - ] + sources += [ "render_text_unittest.cc" ] } # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc index 414c2c9..ff5f8a8 100644 --- a/ui/gfx/canvas.cc +++ b/ui/gfx/canvas.cc
@@ -287,15 +287,19 @@ void Canvas::DrawCircle(const Point& center_point, int radius, const cc::PaintFlags& flags) { - DrawCircle(PointF(center_point), radius, flags); + canvas_->drawOval( + SkRect::MakeLTRB(center_point.x() - radius, center_point.y() - radius, + center_point.x() + radius, center_point.y() + radius), + flags); } void Canvas::DrawCircle(const PointF& center_point, float radius, const cc::PaintFlags& flags) { - canvas_->drawCircle(SkFloatToScalar(center_point.x()), - SkFloatToScalar(center_point.y()), - SkFloatToScalar(radius), flags); + canvas_->drawOval( + SkRect::MakeLTRB(center_point.x() - radius, center_point.y() - radius, + center_point.x() + radius, center_point.y() + radius), + flags); } void Canvas::DrawRoundRect(const Rect& rect,
diff --git a/ui/gl/gl_image_stub.cc b/ui/gl/gl_image_stub.cc index 5bfd62b..3d99c4e7 100644 --- a/ui/gl/gl_image_stub.cc +++ b/ui/gl/gl_image_stub.cc
@@ -21,13 +21,13 @@ bool GLImageStub::BindTexImage(unsigned target) { return true; } bool GLImageStub::CopyTexImage(unsigned target) { - return true; + return false; } bool GLImageStub::CopyTexSubImage(unsigned target, const gfx::Point& offset, const gfx::Rect& rect) { - return true; + return false; } bool GLImageStub::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index 96cfede..dded329 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -28,6 +28,7 @@ deps = [ "//base", "//ui/base", + "//ui/strings", "//url", ] @@ -47,7 +48,6 @@ "//ui/gfx/geometry", "//ui/native_theme", "//ui/resources", - "//ui/strings", ] configs += [
diff --git a/ui/message_center/fake_message_center.cc b/ui/message_center/fake_message_center.cc index 1900b0e6..b1e67185 100644 --- a/ui/message_center/fake_message_center.cc +++ b/ui/message_center/fake_message_center.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "ui/message_center/fake_message_center.h" +#include "base/strings/string_util.h" #include "ui/message_center/notification_list.h" namespace message_center { @@ -142,6 +143,13 @@ void FakeMessageCenter::PausePopupTimers() {} +const base::string16& FakeMessageCenter::GetProductOSName() const { + return base::EmptyString16(); +} + +void FakeMessageCenter::SetProductOSName( + const base::string16& product_os_name) {} + void FakeMessageCenter::DisableTimersForTest() {} void FakeMessageCenter::EnableChangeQueueForTest(bool enabled) {}
diff --git a/ui/message_center/fake_message_center.h b/ui/message_center/fake_message_center.h index 7a8766a..c489f67 100644 --- a/ui/message_center/fake_message_center.h +++ b/ui/message_center/fake_message_center.h
@@ -68,6 +68,8 @@ bool IsMessageCenterVisible() const override; void RestartPopupTimers() override; void PausePopupTimers() override; + const base::string16& GetProductOSName() const override; + void SetProductOSName(const base::string16& product_os_name) override; protected: void DisableTimersForTest() override;
diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h index 55697cb..2eebf0ff 100644 --- a/ui/message_center/message_center.h +++ b/ui/message_center/message_center.h
@@ -193,6 +193,11 @@ // example, after the mouse leaves the popup.) virtual void RestartPopupTimers() = 0; + // "Chromium OS" or "Chrome OS" in the current locale. + // Return empty string if not on these platforms. + virtual const base::string16& GetProductOSName() const = 0; + virtual void SetProductOSName(const base::string16& product_os_name) = 0; + protected: friend class ::DownloadNotification; friend class ::DownloadNotificationTestBase;
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc index c4396746..e2369ca 100644 --- a/ui/message_center/message_center_impl.cc +++ b/ui/message_center/message_center_impl.cc
@@ -15,6 +15,7 @@ #include "base/memory/ptr_util.h" #include "base/observer_list.h" #include "base/stl_util.h" +#include "base/strings/string_util.h" #include "build/build_config.h" #include "ui/message_center/message_center_style.h" #include "ui/message_center/message_center_switches.h" @@ -943,6 +944,15 @@ popup_timers_controller_->PauseAll(); } +const base::string16& MessageCenterImpl::GetProductOSName() const { + return product_os_name_; +} + +void MessageCenterImpl::SetProductOSName( + const base::string16& product_os_name) { + product_os_name_ = product_os_name; +} + void MessageCenterImpl::DisableTimersForTest() { popup_timers_controller_.reset(); }
diff --git a/ui/message_center/message_center_impl.h b/ui/message_center/message_center_impl.h index 3dd9c7f..ea4348a3 100644 --- a/ui/message_center/message_center_impl.h +++ b/ui/message_center/message_center_impl.h
@@ -84,6 +84,8 @@ void EnterQuietModeWithExpire(const base::TimeDelta& expires_in) override; void RestartPopupTimers() override; void PausePopupTimers() override; + const base::string16& GetProductOSName() const override; + void SetProductOSName(const base::string16& product_os_name) override; void ForceNotificationFlush(const std::string& id) override; // NotificationBlocker::Observer overrides: @@ -137,6 +139,8 @@ // center is visible. std::unique_ptr<internal::ChangeQueue> notification_queue_; + base::string16 product_os_name_; + DISALLOW_COPY_AND_ASSIGN(MessageCenterImpl); };
diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h index be5acf24..15102b9 100644 --- a/ui/message_center/message_center_style.h +++ b/ui/message_center/message_center_style.h
@@ -9,6 +9,7 @@ #include "build/build_config.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/size.h" #include "ui/message_center/message_center_export.h" @@ -100,6 +101,15 @@ const SkColor kControlButtonBackgroundColor = SkColorSetA(SK_ColorWHITE, 0.9 * 0xff); +// Accent colors of system notifications. +const SkColor kSystemNotificationColorNormal = SkColorSetRGB(0x33, 0x67, 0xd6); +const SkColor kSystemNotificationColorWarning = SkColorSetRGB(0xea, 0x61, 0x0); +const SkColor kSystemNotificationColorCriticalWarning = + SkColorSetRGB(0xc5, 0x39, 0x29); + +// Default accent color of notifications that are not generated by system. +const SkColor kNotificationDefaultAccentColor = gfx::kChromeIconGrey; + // Limits. // Given the size of an image, returns the size of the properly scaled-up image
diff --git a/ui/message_center/notification.cc b/ui/message_center/notification.cc index c7a7389..1d5a222 100644 --- a/ui/message_center/notification.cc +++ b/ui/message_center/notification.cc
@@ -5,8 +5,15 @@ #include "ui/message_center/notification.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/vector_icon_types.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/message_center_style.h" #include "ui/message_center/notification_delegate.h" #include "ui/message_center/notification_types.h" +#include "ui/strings/grit/ui_strings.h" namespace message_center { @@ -54,7 +61,9 @@ vibration_pattern(other.vibration_pattern), renotify(other.renotify), silent(other.silent), - accessible_name(other.accessible_name) {} + accessible_name(other.accessible_name), + accent_color(other.accent_color) { +} RichNotificationData::~RichNotificationData() = default; @@ -170,14 +179,58 @@ const gfx::Image& icon, const std::string& system_component_id, const base::Closure& click_callback) { - std::unique_ptr<Notification> notification(new Notification( + std::unique_ptr<Notification> notification = CreateSystemNotification( NOTIFICATION_TYPE_SIMPLE, notification_id, title, message, icon, base::string16() /* display_source */, GURL(), NotifierId(NotifierId::SYSTEM_COMPONENT, system_component_id), RichNotificationData(), - new HandleNotificationClickedDelegate(click_callback))); + new HandleNotificationClickedDelegate(click_callback), gfx::kNoneIcon, + SystemNotificationWarningLevel::CRITICAL_WARNING); notification->SetSystemPriority(); return notification; } +// static +std::unique_ptr<Notification> Notification::CreateSystemNotification( + NotificationType type, + const std::string& id, + const base::string16& title, + const base::string16& message, + const gfx::Image& icon, + const base::string16& display_source, + const GURL& origin_url, + const NotifierId& notifier_id, + const RichNotificationData& optional_fields, + scoped_refptr<NotificationDelegate> delegate, + const gfx::VectorIcon& small_image, + SystemNotificationWarningLevel color_type) { + SkColor color = message_center::kSystemNotificationColorNormal; + switch (color_type) { + case SystemNotificationWarningLevel::NORMAL: + color = message_center::kSystemNotificationColorNormal; + break; + case SystemNotificationWarningLevel::WARNING: + color = message_center::kSystemNotificationColorWarning; + break; + case SystemNotificationWarningLevel::CRITICAL_WARNING: + color = message_center::kSystemNotificationColorCriticalWarning; + break; + } + base::string16 display_source_or_default = display_source; + if (display_source_or_default.empty()) { + display_source_or_default = l10n_util::GetStringFUTF16( + IDS_MESSAGE_CENTER_NOTIFICATION_CHROMEOS_SYSTEM, + MessageCenter::Get()->GetProductOSName()); + } + std::unique_ptr<Notification> notification = base::MakeUnique<Notification>( + type, id, title, message, icon, display_source_or_default, origin_url, + notifier_id, optional_fields, delegate); + notification->set_accent_color(color); + notification->set_small_image( + small_image.is_empty() + ? gfx::Image() + : gfx::Image(gfx::CreateVectorIcon(small_image, color))); + return notification; +} + } // namespace message_center
diff --git a/ui/message_center/notification.h b/ui/message_center/notification.h index d08a48a8..8101cad 100644 --- a/ui/message_center/notification.h +++ b/ui/message_center/notification.h
@@ -15,13 +15,19 @@ #include "base/time/time.h" #include "base/values.h" #include "mojo/public/cpp/bindings/struct_traits.h" // nogncheck +#include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/skia_util.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/notification_delegate.h" #include "ui/message_center/notification_types.h" #include "ui/message_center/notifier_settings.h" #include "url/gurl.h" +namespace gfx { +struct VectorIcon; +} // namespace gfx + namespace message_center { namespace mojom { @@ -45,6 +51,8 @@ TEXT }; +enum class SystemNotificationWarningLevel { NORMAL, WARNING, CRITICAL_WARNING }; + // Represents a button to be shown as part of a notification. struct MESSAGE_CENTER_EXPORT ButtonInfo { explicit ButtonInfo(const base::string16& title); @@ -141,6 +149,12 @@ // An accessible description of the notification's contents. base::string16 accessible_name; + + // Unified theme color used in new style notification. + // Usually, it should not be set directly. + // For system notification, CreateSystemNotification with + // SystemNotificationWarningLevel should be used. + SkColor accent_color = SK_ColorTRANSPARENT; }; class MESSAGE_CENTER_EXPORT Notification { @@ -345,6 +359,11 @@ return optional_fields_.accessible_name; } + SkColor accent_color() const { return optional_fields_.accent_color; } + void set_accent_color(SkColor accent_color) { + optional_fields_.accent_color = accent_color; + } + NotificationDelegate* delegate() const { return delegate_.get(); } const RichNotificationData& rich_notification_data() const { @@ -364,6 +383,13 @@ // Helper method to create a simple system notification. |click_callback| // will be invoked when the notification is clicked. + // + // It should only be used for critical notification, as SetSystemPriority and + // CRITICAL_WARNING color are set inside, which means the notification would + // not go away without user interaction. + // + // TODO(tetsui): Add a function parameter |small_image| of gfx::VectorIcon, so + // display source of critical system notification is illustrated by icon. static std::unique_ptr<Notification> CreateSystemNotification( const std::string& notification_id, const base::string16& title, @@ -372,6 +398,25 @@ const std::string& system_component_id, const base::Closure& click_callback); + // Factory method to create all kinds of notifications generated by system, + // from normal priority ones to critical priority ones. + // |small_image| is a small icon show on the upper left header to illustrate + // |display_source| of the notification. + // One specified in the |optional_fields| is overridden. + static std::unique_ptr<Notification> CreateSystemNotification( + NotificationType type, + const std::string& id, + const base::string16& title, + const base::string16& message, + const gfx::Image& icon, + const base::string16& display_source, + const GURL& origin_url, + const NotifierId& notifier_id, + const RichNotificationData& optional_fields, + scoped_refptr<NotificationDelegate> delegate, + const gfx::VectorIcon& small_image, + SystemNotificationWarningLevel color_type); + protected: // The type of notification we'd like displayed. NotificationType type_;
diff --git a/ui/message_center/views/notification_header_view.cc b/ui/message_center/views/notification_header_view.cc index a43e6eaa..5a26331 100644 --- a/ui/message_center/views/notification_header_view.cc +++ b/ui/message_center/views/notification_header_view.cc
@@ -68,8 +68,6 @@ }; ExpandButton::ExpandButton() { - SetImage(gfx::CreateVectorIcon(kNotificationExpandMoreIcon, kExpandIconSize, - gfx::kChromeIconGrey)); focus_painter_ = views::Painter::CreateSolidFocusPainter( kFocusBorderColor, gfx::Insets(1, 2, 2, 2)); SetFocusBehavior(FocusBehavior::ALWAYS); @@ -159,6 +157,7 @@ app_name_view_ = new views::Label(base::string16()); app_name_view_->SetFontList(font_list); app_name_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + app_name_view_->SetEnabledColor(accent_color_); app_info_container->AddChildView(app_name_view_); // Summary text divider @@ -193,6 +192,7 @@ // Expand button view expand_button_ = new ExpandButton(); + SetExpanded(is_expanded_); app_info_container->AddChildView(expand_button_); // Spacer between left-aligned views and right-aligned views @@ -224,6 +224,10 @@ app_icon_view_->SetImage(img); } +void NotificationHeaderView::ClearAppIcon() { + app_icon_view_->SetImage(gfx::CreateVectorIcon(kProductIcon, accent_color_)); +} + void NotificationHeaderView::SetAppName(const base::string16& name) { app_name_view_->SetText(name); } @@ -277,10 +281,10 @@ } void NotificationHeaderView::SetExpanded(bool expanded) { - expand_button_->SetImage( - gfx::CreateVectorIcon( - expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon, - kExpandIconSize, gfx::kChromeIconGrey)); + is_expanded_ = expanded; + expand_button_->SetImage(gfx::CreateVectorIcon( + expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon, + kExpandIconSize, accent_color_)); } void NotificationHeaderView::SetSettingsButtonEnabled(bool enabled) { @@ -304,6 +308,12 @@ } } +void NotificationHeaderView::SetAccentColor(SkColor color) { + accent_color_ = color; + app_name_view_->SetEnabledColor(accent_color_); + SetExpanded(is_expanded_); +} + bool NotificationHeaderView::IsExpandButtonEnabled() { return expand_button_->visible(); }
diff --git a/ui/message_center/views/notification_header_view.h b/ui/message_center/views/notification_header_view.h index 2471c67a..d196eb5a 100644 --- a/ui/message_center/views/notification_header_view.h +++ b/ui/message_center/views/notification_header_view.h
@@ -6,6 +6,7 @@ #define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_HEADER_VIEW_H_ #include "base/macros.h" +#include "ui/message_center/message_center_style.h" #include "ui/message_center/views/padded_button.h" #include "ui/views/controls/button/custom_button.h" @@ -30,6 +31,10 @@ void SetSettingsButtonEnabled(bool enabled); void SetCloseButtonEnabled(bool enabled); void SetControlButtonsVisible(bool visible); + // Set the unified theme color used among the app icon, app name, and expand + // button. + void SetAccentColor(SkColor color); + void ClearAppIcon(); void ClearProgress(); void ClearOverflowIndicator(); void ClearTimestamp(); @@ -53,6 +58,8 @@ // Update visibility for both |summary_text_view_| and |timestamp_view_|. void UpdateSummaryTextVisibility(); + SkColor accent_color_ = message_center::kNotificationDefaultAccentColor; + views::Label* app_name_view_ = nullptr; views::Label* summary_text_divider_ = nullptr; views::Label* summary_text_view_ = nullptr; @@ -69,6 +76,7 @@ bool has_progress_ = false; bool has_overflow_indicator_ = false; bool has_timestamp_ = false; + bool is_expanded_ = false; DISALLOW_COPY_AND_ASSIGN(NotificationHeaderView); };
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc index 09ad6ba..0cbbb7f4 100644 --- a/ui/message_center/views/notification_view_md.cc +++ b/ui/message_center/views/notification_view_md.cc
@@ -58,10 +58,6 @@ constexpr gfx::Size kLargeImageMinSize(328, 0); constexpr gfx::Size kLargeImageMaxSize(328, 218); -// Foreground of small icon image. -constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE; -// Background of small icon image. -const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43); // Background of inline actions area. const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee); // Base ink drop color of action buttons. @@ -87,37 +83,6 @@ message_center::kNotificationWidth - kIconViewSize.width() - kContentRowPadding.left() - kContentRowPadding.right(); -const gfx::ImageSkia CreateSolidColorImage(int width, - int height, - SkColor color) { - SkBitmap bitmap; - bitmap.allocN32Pixels(width, height); - bitmap.eraseColor(color); - return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); -} - -// Take the alpha channel of icon, mask it with the foreground, -// then add the masked foreground on top of the background -const gfx::ImageSkia GetMaskedIcon(const gfx::ImageSkia& icon) { - int width = icon.width(); - int height = icon.height(); - - // Background color grey - const gfx::ImageSkia background = CreateSolidColorImage( - width, height, message_center::kSmallImageBackgroundColor); - // Foreground color white - const gfx::ImageSkia foreground = - CreateSolidColorImage(width, height, message_center::kSmallImageColor); - const gfx::ImageSkia masked_small_image = - gfx::ImageSkiaOperations::CreateMaskedImage(foreground, icon); - return gfx::ImageSkiaOperations::CreateSuperimposedImage(background, - masked_small_image); -} - -const gfx::ImageSkia GetProductIcon() { - return gfx::CreateVectorIcon(kProductIcon, kSmallImageColor); -} - // ItemView //////////////////////////////////////////////////////////////////// // ItemViews are responsible for drawing each list notification item's title and @@ -621,6 +586,10 @@ void NotificationViewMD::CreateOrUpdateContextTitleView( const Notification& notification) { header_row_->SetAppName(notification.display_source()); + header_row_->SetAccentColor( + notification.accent_color() == SK_ColorTRANSPARENT + ? message_center::kNotificationDefaultAccentColor + : notification.accent_color()); header_row_->SetTimestamp(notification.timestamp()); } @@ -805,11 +774,10 @@ void NotificationViewMD::CreateOrUpdateSmallIconView( const Notification& notification) { - gfx::ImageSkia icon = - notification.small_image().IsEmpty() - ? GetProductIcon() - : GetMaskedIcon(notification.small_image().AsImageSkia()); - header_row_->SetAppIcon(icon); + if (notification.small_image().IsEmpty()) + header_row_->ClearAppIcon(); + else + header_row_->SetAppIcon(notification.small_image().AsImageSkia()); } void NotificationViewMD::CreateOrUpdateImageView( @@ -857,6 +825,12 @@ action_buttons_[i]->SchedulePaint(); action_buttons_[i]->Layout(); } + + // Change action button color to the accent color. + action_buttons_[i]->SetEnabledTextColors(notification.accent_color() == + SK_ColorTRANSPARENT + ? kActionButtonTextColor + : notification.accent_color()); } // Inherit mouse hover state when action button views reset.