diff --git a/DEPS b/DEPS index 6728ebe2d..fd93a5d4 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'ddebefb50ab52b968fed0f9957c419e7acd2326f', + 'v8_revision': 'e9521a836dcd6a912141a999589bee67bab92f6d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'd7403971a25c317671e92ccc676a5f600ed223eb', + 'pdfium_revision': 'fb00ec2af390ccfe8f5e81f49b9113e044f5e5ad', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -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': '34ef95cb09ce13d370163e36179981f566356c68', + 'catapult_revision': 'a5b1645083bd1cfad24a6bef274092407c196b1f', # 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/ash/public/interfaces/wallpaper.mojom b/ash/public/interfaces/wallpaper.mojom index 7215c31..02edb35c 100644 --- a/ash/public/interfaces/wallpaper.mojom +++ b/ash/public/interfaces/wallpaper.mojom
@@ -11,6 +11,10 @@ // Used by Chrome to set the wallpaper displayed by ash. interface WallpaperController { + // Calling this method triggers an initial notification of the wallpaper + // state. Observers are automatically removed as their connections are closed. + AddObserver(associated WallpaperObserver observer); + // Set the wallpaper picker interface, to let ash trigger Chrome's picker. SetWallpaperPicker(WallpaperPicker picker); @@ -19,6 +23,18 @@ // TODO(crbug.com/655875): Optimize ash wallpaper transport; avoid sending // large bitmaps over Mojo; use shared memory like BitmapUploader, etc. SetWallpaper(skia.mojom.Bitmap? wallpaper, WallpaperLayout layout); + + // Runs to get wallpaper prominent colors. + GetWallpaperColors() => (array<uint32> prominent_colors); +}; + +// Used to listen for wallpaper state changed. +interface WallpaperObserver { + // Called when the colors extracted from the current wallpaper change. May + // be called as a side effect of changing the wallpaper on the + // WallpaperController, e.g. WallpaperController::SetWallpaperImage(). + // Colors are ordered and are referenced in wallpaper::ColorProfileType. + OnWallpaperColorsChanged(array<uint32> prominent_colors); }; // Used by ash to trigger Chrome's wallpaper picker functionality.
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index 7d2e5ca..e594db7 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -23,6 +23,7 @@ #include "base/sequenced_task_runner.h" #include "base/task_scheduler/post_task.h" #include "components/wallpaper/wallpaper_color_calculator.h" +#include "components/wallpaper/wallpaper_color_profile.h" #include "components/wallpaper/wallpaper_resizer.h" #include "ui/display/manager/display_manager.h" #include "ui/display/manager/managed_display_info.h" @@ -34,6 +35,7 @@ using color_utils::ColorProfile; using color_utils::LumaRange; using color_utils::SaturationRange; +using wallpaper::ColorProfileType; namespace ash { @@ -45,17 +47,6 @@ // How long to wait for resizing of the the wallpaper. constexpr int kCompositorLockTimeoutMs = 750; -// This enum is used to get the corresponding prominent color from the -// calculation results. -enum ColorProfileIndex { - COLOR_PROFILE_INDEX_DARK_VIBRANT = 0, - COLOR_PROFILE_INDEX_NORMAL_VIBRANT, - COLOR_PROFILE_INDEX_LIGHT_VIBRANT, - COLOR_PROFILE_INDEX_DARK_MUTED, - COLOR_PROFILE_INDEX_NORMAL_MUTED, - COLOR_PROFILE_INDEX_LIGHT_MUTED, -}; - // Returns true if a color should be extracted from the wallpaper based on the // command kAshShelfColor line arg. bool IsShelfColoringEnabled() { @@ -90,30 +81,30 @@ ColorProfile(LumaRange::LIGHT, SaturationRange::MUTED)}; } -// Gets the corresponding color profile index based on the given +// Gets the corresponding color profile type based on the given // |color_profile|. -ColorProfileIndex GetColorProfileIndex(ColorProfile color_profile) { +ColorProfileType GetColorProfileType(ColorProfile color_profile) { if (color_profile.saturation == SaturationRange::VIBRANT) { switch (color_profile.luma) { case LumaRange::DARK: - return COLOR_PROFILE_INDEX_DARK_VIBRANT; + return ColorProfileType::DARK_VIBRANT; case LumaRange::NORMAL: - return COLOR_PROFILE_INDEX_NORMAL_VIBRANT; + return ColorProfileType::NORMAL_VIBRANT; case LumaRange::LIGHT: - return COLOR_PROFILE_INDEX_LIGHT_VIBRANT; + return ColorProfileType::LIGHT_VIBRANT; } } else { switch (color_profile.luma) { case LumaRange::DARK: - return COLOR_PROFILE_INDEX_DARK_MUTED; + return ColorProfileType::DARK_MUTED; case LumaRange::NORMAL: - return COLOR_PROFILE_INDEX_NORMAL_MUTED; + return ColorProfileType::NORMAL_MUTED; case LumaRange::LIGHT: - return COLOR_PROFILE_INDEX_LIGHT_MUTED; + return ColorProfileType::LIGHT_MUTED; } } NOTREACHED(); - return COLOR_PROFILE_INDEX_DARK_MUTED; + return ColorProfileType::DARK_MUTED; } } // namespace @@ -173,8 +164,8 @@ SkColor WallpaperController::GetProminentColor( ColorProfile color_profile) const { - ColorProfileIndex index = GetColorProfileIndex(color_profile); - return prominent_colors_[index]; + ColorProfileType type = GetColorProfileType(color_profile); + return prominent_colors_[static_cast<int>(type)]; } wallpaper::WallpaperLayout WallpaperController::GetWallpaperLayout() const { @@ -305,6 +296,14 @@ } } +void WallpaperController::AddObserver( + mojom::WallpaperObserverAssociatedPtrInfo observer) { + mojom::WallpaperObserverAssociatedPtr observer_ptr; + observer_ptr.Bind(std::move(observer)); + observer_ptr->OnWallpaperColorsChanged(prominent_colors_); + mojo_observers_.AddPtr(std::move(observer_ptr)); +} + void WallpaperController::SetWallpaperPicker(mojom::WallpaperPickerPtr picker) { wallpaper_picker_ = std::move(picker); } @@ -317,6 +316,11 @@ SetWallpaperImage(gfx::ImageSkia::CreateFrom1xBitmap(wallpaper), layout); } +void WallpaperController::GetWallpaperColors( + GetWallpaperColorsCallback callback) { + std::move(callback).Run(prominent_colors_); +} + void WallpaperController::OnWallpaperResized() { CalculateWallpaperColors(); compositor_lock_.reset(); @@ -403,6 +407,9 @@ prominent_colors_ = colors; for (auto& observer : observers_) observer.OnWallpaperColorsChanged(); + mojo_observers_.ForAllPtrs([this](mojom::WallpaperObserver* observer) { + observer->OnWallpaperColorsChanged(prominent_colors_); + }); } void WallpaperController::CalculateWallpaperColors() {
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h index 74919b2..6c224f65 100644 --- a/ash/wallpaper/wallpaper_controller.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -19,6 +19,7 @@ #include "components/wallpaper/wallpaper_layout.h" #include "components/wallpaper/wallpaper_resizer_observer.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_ptr_set.h" #include "ui/compositor/compositor_lock.h" namespace base { @@ -122,9 +123,11 @@ void OpenSetWallpaperPage(); // mojom::WallpaperController overrides: + void AddObserver(mojom::WallpaperObserverAssociatedPtrInfo observer) override; void SetWallpaperPicker(mojom::WallpaperPickerPtr picker) override; void SetWallpaper(const SkBitmap& wallpaper, wallpaper::WallpaperLayout layout) override; + void GetWallpaperColors(GetWallpaperColorsCallback callback) override; // WallpaperResizerObserver: void OnWallpaperResized() override; @@ -195,6 +198,8 @@ base::ObserverList<WallpaperControllerObserver> observers_; + mojo::AssociatedInterfacePtrSet<mojom::WallpaperObserver> mojo_observers_; + std::unique_ptr<wallpaper::WallpaperResizer> current_wallpaper_; // Asynchronous task to extract colors from the wallpaper.
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index cf8c2d1..f8d1599 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -23,6 +23,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/task_scheduler/task_scheduler.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/aura/window.h" @@ -106,6 +107,28 @@ } } +// A test implementation of the WallpaperObserver mojo interface. +class TestWallpaperObserver : public mojom::WallpaperObserver { + public: + TestWallpaperObserver() = default; + ~TestWallpaperObserver() override = default; + + // mojom::WallpaperObserver: + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override { + ++wallpaper_colors_changed_count_; + } + + int wallpaper_colors_changed_count() const { + return wallpaper_colors_changed_count_; + } + + private: + int wallpaper_colors_changed_count_ = 0; + + DISALLOW_COPY_AND_ASSIGN(TestWallpaperObserver); +}; + } // namespace class WallpaperControllerTest : public test::AshTestBase { @@ -529,4 +552,25 @@ EXPECT_FALSE(ShouldCalculateColors()); } +TEST_F(WallpaperControllerTest, MojoWallpaperObserverTest) { + TestWallpaperObserver observer; + mojom::WallpaperObserverAssociatedPtr observer_ptr; + mojo::AssociatedBinding<mojom::WallpaperObserver> binding( + &observer, mojo::MakeIsolatedRequest(&observer_ptr)); + controller_->AddObserver(observer_ptr.PassInterface()); + + // Mojo observer will asynchronously receive the observed event, thus a run + // loop needs to be spinned. + base::RunLoop().RunUntilIdle(); + // When adding observer, OnWallpaperColorsChanged() is fired so that we start + // with count equals 1. + EXPECT_EQ(1, observer.wallpaper_colors_changed_count()); + + // Enable shelf coloring will set a customized wallpaper image and change + // session state to ACTIVE, which will trigger wallpaper colors calculation. + EnableShelfColoring(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(2, observer.wallpaper_colors_changed_count()); +} + } // namespace ash
diff --git a/base/files/file_enumerator_posix.cc b/base/files/file_enumerator_posix.cc index bc5c3cc5..ce1fe40a 100644 --- a/base/files/file_enumerator_posix.cc +++ b/base/files/file_enumerator_posix.cc
@@ -125,7 +125,7 @@ FileInfo dotdot; dotdot.stat_.st_mode = S_IFDIR; dotdot.filename_ = FilePath(".."); - directory_entries_->push_back(dotdot); + directory_entries_.push_back(dotdot); #endif // OS_FUCHSIA current_directory_entry_ = 0;
diff --git a/build/config/mac/BuildInfo.plist b/build/config/mac/BuildInfo.plist index b0856e35..d32bf2ea7 100644 --- a/build/config/mac/BuildInfo.plist +++ b/build/config/mac/BuildInfo.plist
@@ -14,13 +14,5 @@ <string>${XCODE_VERSION}</string> <key>DTXcodeBuild</key> <string>${XCODE_BUILD}</string> - <key>CFBundleShortVersionString</key> - <string>${VERSION}</string> - <key>CFBundleVersion</key> - <string>${VERSION_BUILD}</string> - <key>CFBundleIdentifier</key> - <string>org.chromium.${PRODUCT_NAME:rfc1034identifier}</string> - <key>SCM_REVISION</key> - <string>${COMMIT_HASH}</string> </dict> </plist>
diff --git a/build/config/mac/plist_util.py b/build/config/mac/plist_util.py index 0928fa13..dd6fe4c 100644 --- a/build/config/mac/plist_util.py +++ b/build/config/mac/plist_util.py
@@ -21,25 +21,13 @@ IDENT_RE = re.compile(r'[_/\s]') -def InterpolateList(values, substitutions): - """Interpolates variable references into |value| using |substitutions|. +class SubstitutionError(Exception): + def __init__(self, key): + super(SubstitutionError, self).__init__() + self.key = key - Inputs: - values: a list of values - substitutions: a mapping of variable names to values - - Returns: - A new list of values with all variables references ${VARIABLE} replaced - by their value in |substitutions| or None if any of the variable has no - subsitution. - """ - result = [] - for value in values: - interpolated = InterpolateValue(value, substitutions) - if interpolated is None: - return None - result.append(interpolated) - return result + def __str__(self): + return "SubstitutionError: {}".format(self.key) def InterpolateString(value, substitutions): @@ -51,29 +39,28 @@ Returns: A new string with all variables references ${VARIABLES} replaced by their - value in |substitutions| or None if any of the variable has no substitution. + value in |substitutions|. Raises SubstitutionError if a variable has no + substitution. """ - result = value - for match in reversed(list(SUBST_RE.finditer(value))): + def repl(match): variable = match.group('id') if variable not in substitutions: - return None + raise SubstitutionError(variable) # Some values need to be identifier and thus the variables references may # contains :modifier attributes to indicate how they should be converted # to identifiers ("identifier" replaces all invalid characters by '_' and # "rfc1034identifier" replaces them by "-" to make valid URI too). modifier = match.group('modifier') if modifier == ':identifier': - interpolated = IDENT_RE.sub('_', substitutions[variable]) + return IDENT_RE.sub('_', substitutions[variable]) elif modifier == ':rfc1034identifier': - interpolated = IDENT_RE.sub('-', substitutions[variable]) + return IDENT_RE.sub('-', substitutions[variable]) else: - interpolated = substitutions[variable] - result = result[:match.start()] + interpolated + result[match.end():] - return result + return substitutions[variable] + return SUBST_RE.sub(repl, value) -def InterpolateValue(value, substitutions): +def Interpolate(value, substitutions): """Interpolates variable references into |value| using |substitutions|. Inputs: @@ -82,38 +69,18 @@ Returns: A new value with all variables references ${VARIABLES} replaced by their - value in |substitutions| or None if any of the variable has no substitution. + value in |substitutions|. Raises SubstitutionError if a variable has no + substitution. """ if isinstance(value, dict): - return Interpolate(value, substitutions) + return {k: Interpolate(v, substitutions) for k, v in value.iteritems()} if isinstance(value, list): - return InterpolateList(value, substitutions) + return [Interpolate(v, substitutions) for v in value] if isinstance(value, str): return InterpolateString(value, substitutions) return value -def Interpolate(plist, substitutions): - """Interpolates variable references into |value| using |substitutions|. - - Inputs: - plist: a dictionary representing a Property List (.plist) file - substitutions: a mapping of variable names to values - - Returns: - A new plist with all variables references ${VARIABLES} replaced by their - value in |substitutions|. All values that contains references with no - substitutions will be removed and the corresponding key will be cleared - from the plist (not recursively). - """ - result = {} - for key in plist: - value = InterpolateValue(plist[key], substitutions) - if value is not None: - result[key] = value - return result - - def LoadPList(path): """Loads Plist at |path| and returns it as a dictionary.""" fd, name = tempfile.mkstemp() @@ -153,19 +120,12 @@ recursively, otherwise |plist2| value is used. If values are list, they are concatenated. """ - if not isinstance(plist1, dict) or not isinstance(plist2, dict): - if plist2 is not None: - return plist2 - else: - return plist1 - result = {} - for key in set(plist1) | set(plist2): - if key in plist2: - value = plist2[key] - else: - value = plist1[key] + result = plist1.copy() + for key, value in plist2.iteritems(): if isinstance(value, dict): - value = MergePList(plist1.get(key, None), plist2.get(key, None)) + old_value = result.get(key) + if isinstance(old_value, dict): + value = MergePList(old_value, value) if isinstance(value, list): value = plist1.get(key, []) + plist2.get(key, []) result[key] = value
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index 57de616..1c53186 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -25,6 +25,10 @@ "paint_image.h", "paint_op_buffer.cc", "paint_op_buffer.h", + "paint_op_reader.cc", + "paint_op_reader.h", + "paint_op_writer.cc", + "paint_op_writer.h", "paint_record.cc", "paint_record.h", "paint_recorder.cc",
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h index 6954892d..940751c 100644 --- a/cc/paint/paint_flags.h +++ b/cc/paint/paint_flags.h
@@ -224,6 +224,9 @@ bool SupportsFoldingAlpha() const; private: + friend class PaintOpReader; + friend class PaintOpWriter; + friend const SkPaint& ToSkPaint(const PaintFlags& flags); friend const SkPaint* ToSkPaint(const PaintFlags* flags);
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 981622d..644b8550 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -6,6 +6,8 @@ #include "base/containers/stack_container.h" #include "cc/paint/display_item_list.h" +#include "cc/paint/paint_op_reader.h" +#include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -136,6 +138,24 @@ static_assert(kNumOpTypes == TYPES(M), "Missing op in list"); #undef M +using SerializeFunction = size_t (*)(const PaintOp* op, + void* memory, + size_t size, + const PaintOp::SerializeOptions& options); +#define M(T) &T::Serialize, +static const SerializeFunction g_serialize_functions[kNumOpTypes] = {TYPES(M)}; +#undef M + +using DeserializeFunction = PaintOp* (*)(const void* input, + size_t input_size, + void* output, + size_t output_size); + +#define M(T) &T::Deserialize, +static const DeserializeFunction g_deserialize_functions[kNumOpTypes] = { + TYPES(M)}; +#undef M + using RasterFunction = void (*)(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); @@ -187,6 +207,7 @@ #undef TYPES SkRect PaintOp::kUnsetRect = {SK_ScalarInfinity, 0, 0, 0}; +const size_t PaintOp::kMaxSkip; std::string PaintOpTypeToString(PaintOpType type) { switch (type) { @@ -254,6 +275,782 @@ return "UNKNOWN"; } +template <typename T> +size_t SimpleSerialize(const PaintOp* op, void* memory, size_t size) { + if (sizeof(T) > size) + return 0; + memcpy(memory, op, sizeof(T)); + return sizeof(T); +} + +size_t AnnotateOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const AnnotateOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->annotation_type); + helper.Write(op->rect); + helper.Write(op->data); + return helper.size(); +} + +size_t ClipPathOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const ClipPathOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->path); + helper.Write(op->op); + helper.Write(op->antialias); + return helper.size(); +} + +size_t ClipRectOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ClipRectOp>(op, memory, size); +} + +size_t ClipRRectOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ClipRRectOp>(op, memory, size); +} + +size_t ConcatOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ConcatOp>(op, memory, size); +} + +size_t DrawArcOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawArcOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->oval); + helper.Write(op->start_angle); + helper.Write(op->sweep_angle); + helper.Write(op->use_center); + 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, + const SerializeOptions& options) { + return SimpleSerialize<DrawColorOp>(op, memory, size); +} + +size_t DrawDRRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawDRRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->outer); + helper.Write(op->inner); + return helper.size(); +} + +size_t DrawImageOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawImageOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->image, options.decode_cache); + helper.Write(op->left); + helper.Write(op->top); + return helper.size(); +} + +size_t DrawImageRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawImageRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->image, options.decode_cache); + helper.Write(op->src); + helper.Write(op->dst); + helper.Write(op->constraint); + return helper.size(); +} + +size_t DrawIRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawIRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->rect); + return helper.size(); +} + +size_t DrawLineOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawLineOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->x0); + helper.Write(op->y0); + helper.Write(op->x1); + helper.Write(op->y1); + return helper.size(); +} + +size_t DrawOvalOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawOvalOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->oval); + return helper.size(); +} + +size_t DrawPathOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawPathOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->path); + return helper.size(); +} + +size_t DrawPosTextOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawPosTextOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->count); + helper.Write(op->bytes); + helper.WriteArray(op->count, op->GetArray()); + helper.WriteData(op->bytes, op->GetData()); + return helper.size(); +} + +size_t DrawRecordOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + // TODO(enne): these must be flattened. Serializing this will not do + // anything. + NOTREACHED(); + return 0u; +} + +size_t DrawRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->rect); + return helper.size(); +} + +size_t DrawRRectOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawRRectOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->rrect); + return helper.size(); +} + +size_t DrawTextOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawTextOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->x); + helper.Write(op->y); + helper.Write(op->bytes); + helper.WriteData(op->bytes, op->GetData()); + return helper.size(); +} + +size_t DrawTextBlobOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const DrawTextBlobOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->x); + helper.Write(op->y); + helper.Write(op->blob); + return helper.size(); +} + +size_t NoopOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<NoopOp>(op, memory, size); +} + +size_t RestoreOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<RestoreOp>(op, memory, size); +} + +size_t RotateOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<RotateOp>(op, memory, size); +} + +size_t SaveOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<SaveOp>(op, memory, size); +} + +size_t SaveLayerOp::Serialize(const PaintOp* base_op, + void* memory, + size_t size, + const SerializeOptions& options) { + auto* op = static_cast<const SaveLayerOp*>(base_op); + PaintOpWriter helper(memory, size); + helper.Write(op->flags); + helper.Write(op->bounds); + return helper.size(); +} + +size_t SaveLayerAlphaOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<SaveLayerAlphaOp>(op, memory, size); +} + +size_t ScaleOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<ScaleOp>(op, memory, size); +} + +size_t SetMatrixOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<SetMatrixOp>(op, memory, size); +} + +size_t TranslateOp::Serialize(const PaintOp* op, + void* memory, + size_t size, + const SerializeOptions& options) { + return SimpleSerialize<TranslateOp>(op, memory, size); +} + +template <typename T> +void UpdateTypeAndSkip(T* op) { + op->type = static_cast<uint8_t>(T::kType); + op->skip = MathUtil::UncheckedRoundUp(sizeof(T), PaintOpBuffer::PaintOpAlign); +} + +template <typename T> +PaintOp* SimpleDeserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + if (input_size < sizeof(T)) + return nullptr; + memcpy(output, input, sizeof(T)); + + T* op = reinterpret_cast<T*>(output); + // Type and skip were already read once, so could have been changed. + // Don't trust them and clobber them with something valid. + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* AnnotateOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(AnnotateOp)); + AnnotateOp* op = new (output) AnnotateOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->annotation_type); + helper.Read(&op->rect); + helper.Read(&op->data); + if (!helper.valid()) { + op->~AnnotateOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* ClipPathOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(ClipPathOp)); + ClipPathOp* op = new (output) ClipPathOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->path); + helper.Read(&op->op); + helper.Read(&op->antialias); + if (!helper.valid()) { + op->~ClipPathOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* ClipRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ClipRectOp>(input, input_size, output, output_size); +} + +PaintOp* ClipRRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ClipRRectOp>(input, input_size, output, output_size); +} + +PaintOp* ConcatOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ConcatOp>(input, input_size, output, output_size); +} + +PaintOp* DrawArcOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawArcOp)); + DrawArcOp* op = new (output) DrawArcOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->oval); + helper.Read(&op->start_angle); + helper.Read(&op->sweep_angle); + helper.Read(&op->use_center); + if (!helper.valid()) { + op->~DrawArcOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawCircleOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_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->~DrawCircleOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawColorOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<DrawColorOp>(input, input_size, output, output_size); +} + +PaintOp* DrawDRRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawDRRectOp)); + DrawDRRectOp* op = new (output) DrawDRRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->outer); + helper.Read(&op->inner); + if (!helper.valid()) { + op->~DrawDRRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawImageOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawImageOp)); + DrawImageOp* op = new (output) DrawImageOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->image); + helper.Read(&op->left); + helper.Read(&op->top); + if (!helper.valid()) { + op->~DrawImageOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawImageRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawImageRectOp)); + DrawImageRectOp* op = new (output) DrawImageRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->image); + helper.Read(&op->src); + helper.Read(&op->dst); + helper.Read(&op->constraint); + if (!helper.valid()) { + op->~DrawImageRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawIRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawIRectOp)); + DrawIRectOp* op = new (output) DrawIRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->rect); + if (!helper.valid()) { + op->~DrawIRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawLineOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawLineOp)); + DrawLineOp* op = new (output) DrawLineOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->x0); + helper.Read(&op->y0); + helper.Read(&op->x1); + helper.Read(&op->y1); + if (!helper.valid()) { + op->~DrawLineOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawOvalOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawOvalOp)); + DrawOvalOp* op = new (output) DrawOvalOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->oval); + if (!helper.valid()) { + op->~DrawOvalOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawPathOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawPathOp)); + DrawPathOp* op = new (output) DrawPathOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->path); + if (!helper.valid()) { + op->~DrawPathOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawPosTextOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + // TODO(enne): This is a bit of a weird condition, but to avoid the code + // complexity of every Deserialize function being able to (re)allocate + // an aligned buffer of the right size, this function asserts that it + // will have enough size for the extra data. It's guaranteed that any extra + // memory is at most |input_size| so that plus the op size is an upper bound. + // The caller has to awkwardly do this allocation though, sorry. + CHECK_GE(output_size, sizeof(DrawPosTextOp) + input_size); + DrawPosTextOp* op = new (output) DrawPosTextOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->count); + helper.Read(&op->bytes); + helper.ReadArray(op->count, op->GetArray()); + helper.ReadData(op->bytes, op->GetData()); + if (!helper.valid()) { + op->~DrawPosTextOp(); + return nullptr; + } + + op->type = static_cast<uint8_t>(PaintOpType::DrawPosText); + op->skip = MathUtil::UncheckedRoundUp( + sizeof(DrawPosTextOp) + op->bytes + sizeof(SkPoint) * op->count, + PaintOpBuffer::PaintOpAlign); + + return op; +} + +PaintOp* DrawRecordOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + // TODO(enne): these must be flattened and not sent directly. + // TODO(enne): could also consider caching these service side. + NOTREACHED(); + return nullptr; +} + +PaintOp* DrawRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawRectOp)); + DrawRectOp* op = new (output) DrawRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->rect); + if (!helper.valid()) { + op->~DrawRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawRRectOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawRRectOp)); + DrawRRectOp* op = new (output) DrawRRectOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->rrect); + if (!helper.valid()) { + op->~DrawRRectOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* DrawTextOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawTextOp) + input_size); + DrawTextOp* op = new (output) DrawTextOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->x); + helper.Read(&op->y); + helper.Read(&op->bytes); + helper.ReadData(op->bytes, op->GetData()); + if (!helper.valid()) { + op->~DrawTextOp(); + return nullptr; + } + + op->type = static_cast<uint8_t>(PaintOpType::DrawText); + op->skip = MathUtil::UncheckedRoundUp(sizeof(DrawTextOp) + op->bytes, + PaintOpBuffer::PaintOpAlign); + return op; +} + +PaintOp* DrawTextBlobOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(DrawTextBlobOp)); + DrawTextBlobOp* op = new (output) DrawTextBlobOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->x); + helper.Read(&op->y); + helper.Read(&op->blob); + if (!helper.valid()) { + op->~DrawTextBlobOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* NoopOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<NoopOp>(input, input_size, output, output_size); +} + +PaintOp* RestoreOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<RestoreOp>(input, input_size, output, output_size); +} + +PaintOp* RotateOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<RotateOp>(input, input_size, output, output_size); +} + +PaintOp* SaveOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<SaveOp>(input, input_size, output, output_size); +} + +PaintOp* SaveLayerOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + CHECK_GE(output_size, sizeof(SaveLayerOp)); + SaveLayerOp* op = new (output) SaveLayerOp; + + PaintOpReader helper(input, input_size); + helper.Read(&op->flags); + helper.Read(&op->bounds); + if (!helper.valid()) { + op->~SaveLayerOp(); + return nullptr; + } + UpdateTypeAndSkip(op); + return op; +} + +PaintOp* SaveLayerAlphaOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<SaveLayerAlphaOp>(input, input_size, output, + output_size); +} + +PaintOp* ScaleOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<ScaleOp>(input, input_size, output, output_size); +} + +PaintOp* SetMatrixOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<SetMatrixOp>(input, input_size, output, output_size); +} + +PaintOp* TranslateOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + return SimpleDeserialize<TranslateOp>(input, input_size, output, output_size); +} + void AnnotateOp::Raster(const PaintOp* base_op, SkCanvas* canvas, const SkMatrix& original_ctm) { @@ -516,6 +1313,59 @@ g_raster_alpha_functions[type](this, canvas, bounds, alpha); } +size_t PaintOp::Serialize(void* memory, + size_t size, + const SerializeOptions& options) const { + // Need at least enough room for a skip/type header. + if (size < 4) + return 0u; + + DCHECK_EQ(0u, + reinterpret_cast<uintptr_t>(memory) % PaintOpBuffer::PaintOpAlign); + + size_t written = g_serialize_functions[type](this, memory, size, options); + DCHECK_LE(written, size); + if (written < 4) + return 0u; + + size_t aligned_written = + MathUtil::UncheckedRoundUp(written, PaintOpBuffer::PaintOpAlign); + if (aligned_written >= kMaxSkip) + return 0u; + if (aligned_written > size) + return 0u; + + // Update skip and type now that the size is known. + uint32_t skip = static_cast<uint32_t>(aligned_written); + static_cast<uint32_t*>(memory)[0] = type | skip << 8; + return skip; +} + +PaintOp* PaintOp::Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size) { + // TODO(enne): assert that output_size is big enough. + const PaintOp* serialized = reinterpret_cast<const PaintOp*>(input); + uint32_t skip = serialized->skip; + if (input_size < skip) + return nullptr; + if (skip % PaintOpBuffer::PaintOpAlign != 0) + return nullptr; + uint8_t type = serialized->type; + if (type > static_cast<uint8_t>(PaintOpType::LastPaintOpType)) + return nullptr; + + return g_deserialize_functions[serialized->type](input, skip, output, + output_size); +} + +void PaintOp::DestroyThis() { + auto func = g_destructor_functions[type]; + if (func) + func(this); +} + int ClipPathOp::CountSlowPaths() const { return antialias && !path.isConvex() ? 1 : 0; } @@ -563,6 +1413,8 @@ return record->HasNonAAPaint(); } +AnnotateOp::AnnotateOp() = default; + AnnotateOp::AnnotateOp(PaintCanvas::AnnotationType annotation_type, const SkRect& rect, sk_sp<SkData> data) @@ -587,6 +1439,8 @@ DrawImageOp::~DrawImageOp() = default; +DrawImageRectOp::DrawImageRectOp() = default; + DrawImageRectOp::DrawImageRectOp(const PaintImage& image, const SkRect& src, const SkRect& dst, @@ -604,6 +1458,8 @@ DrawImageRectOp::~DrawImageRectOp() = default; +DrawPosTextOp::DrawPosTextOp() = default; + DrawPosTextOp::DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags) @@ -611,6 +1467,8 @@ DrawPosTextOp::~DrawPosTextOp() = default; +DrawRecordOp::DrawRecordOp() = default; + DrawRecordOp::DrawRecordOp(sk_sp<const PaintRecord> record) : record(std::move(record)) {} @@ -624,6 +1482,8 @@ return record->HasDiscardableImages(); } +DrawTextBlobOp::DrawTextBlobOp() = default; + DrawTextBlobOp::DrawTextBlobOp(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y, @@ -658,11 +1518,8 @@ } void PaintOpBuffer::Reset() { - for (auto* op : Iterator(this)) { - auto func = g_destructor_functions[op->type]; - if (func) - func(op); - } + for (auto* op : Iterator(this)) + op->DestroyThis(); // Leave data_ allocated, reserved_ unchanged. used_ = 0; @@ -793,7 +1650,7 @@ // Compute a skip such that all ops in the buffer are aligned to the // maximum required alignment of all ops. size_t skip = MathUtil::UncheckedRoundUp(sizeof_op + bytes, PaintOpAlign); - DCHECK_LT(skip, static_cast<size_t>(1) << 24); + DCHECK_LT(skip, PaintOp::kMaxSkip); if (used_ + skip > reserved_) { // Start reserved_ at kInitialBufferSize and then double. // ShrinkToFit can make this smaller afterwards.
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index d3cba68a2..fbbb65d6c 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -27,6 +27,8 @@ namespace cc { +class ImageDecodeCache; + class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix { public: explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) { @@ -39,8 +41,18 @@ explicit ThreadsafePath(const SkPath& path) : SkPath(path) { updateBoundsCache(); } + ThreadsafePath() { updateBoundsCache(); } }; +// See PaintOp::Serialize/Deserialize for comments. Derived Serialize types +// don't write the 4 byte type/skip header because they don't know how much +// data they will need to write. PaintOp::Serialize itself must update it. +#define HAS_SERIALIZATION_FUNCTIONS() \ + static size_t Serialize(const PaintOp* op, void* memory, size_t size, \ + const SerializeOptions& options); \ + static PaintOp* Deserialize(const void* input, size_t input_size, \ + void* output, size_t output_size); + enum class PaintOpType : uint8_t { Annotate, ClipPath, @@ -75,9 +87,10 @@ LastPaintOpType = Translate, }; -std::string PaintOpTypeToString(PaintOpType type); +CC_PAINT_EXPORT std::string PaintOpTypeToString(PaintOpType type); -struct CC_PAINT_EXPORT PaintOp { +class CC_PAINT_EXPORT PaintOp { + public: uint32_t type : 8; uint32_t skip : 24; @@ -90,6 +103,28 @@ void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const; bool IsDrawOp() const; + struct SerializeOptions { + ImageDecodeCache* decode_cache = nullptr; + }; + + // Subclasses should provide a static Serialize() method called from here. + // If the op can be serialized to |memory| in no more than |size| bytes, + // then return the number of bytes written. If it won't fit, return 0. + size_t Serialize(void* memory, + size_t size, + const SerializeOptions& options) const; + + // Deserializes a PaintOp of this type from a given buffer |input| of + // at most |input_size| bytes. Returns null on any errors. + // The PaintOp is deserialized into the |output| buffer and returned + // if valid. nullptr is returned if the deserialization fails. + // |output_size| must be at least LargestPaintOp + serialized->skip, + // to fit all ops. The caller is responsible for destroying these ops. + static PaintOp* Deserialize(const void* input, + size_t input_size, + void* output, + size_t output_size); + // Only valid for draw ops. void RasterWithAlpha(SkCanvas* canvas, const SkRect& bounds, @@ -107,14 +142,20 @@ // and display lists. This doesn't count other objects like paths or blobs. size_t AdditionalBytesUsed() const { return 0; } + // Run the destructor for the derived op type. Ops are usually contained in + // memory buffers and so don't have their destructors run automatically. + void DestroyThis(); + static constexpr bool kIsDrawOp = false; static constexpr bool kHasPaintFlags = false; + // Since skip and type fit in a uint32_t, this is the max size of skip. + static constexpr size_t kMaxSkip = static_cast<size_t>(1 << 24); static SkRect kUnsetRect; }; -struct CC_PAINT_EXPORT PaintOpWithFlags : PaintOp { +class CC_PAINT_EXPORT PaintOpWithFlags : public PaintOp { + public: static constexpr bool kHasPaintFlags = true; - explicit PaintOpWithFlags(const PaintFlags& flags) : flags(flags) {} int CountSlowPathsFromFlags() const { return flags.getPathEffect() ? 1 : 0; } @@ -135,9 +176,13 @@ // a const PaintOpWithFlags* parameter so that it can be used as a function // pointer. PaintFlags flags; + + protected: + PaintOpWithFlags() = default; }; -struct CC_PAINT_EXPORT PaintOpWithData : PaintOpWithFlags { +class CC_PAINT_EXPORT PaintOpWithData : public PaintOpWithFlags { + public: // Having data is just a helper for ops that have a varying amount of data and // want a way to store that inline. This is for ops that pass in a // void* and a length. The void* data is assumed to not have any alignment @@ -150,6 +195,8 @@ size_t bytes; protected: + PaintOpWithData() = default; + // For some derived object T, return the internally stored data. // This needs the fully derived type to know how much to offset // from the start of the top to the data. @@ -173,13 +220,18 @@ } }; -struct CC_PAINT_EXPORT PaintOpWithArrayBase : PaintOpWithFlags { +class CC_PAINT_EXPORT PaintOpWithArrayBase : public PaintOpWithFlags { + public: explicit PaintOpWithArrayBase(const PaintFlags& flags) : PaintOpWithFlags(flags) {} + + protected: + PaintOpWithArrayBase() = default; }; template <typename M> -struct CC_PAINT_EXPORT PaintOpWithArray : PaintOpWithArrayBase { +class CC_PAINT_EXPORT PaintOpWithArray : public PaintOpWithArrayBase { + public: // Paint op that has a M[count] and a char[bytes]. // Array data is stored first so that it can be aligned with T's alignment // with the arbitrary unaligned char data after it. @@ -192,6 +244,8 @@ size_t count; protected: + PaintOpWithArray() = default; + template <typename T> const void* GetDataForThis(const T* op) const { static_assert(std::is_convertible<T, PaintOpWithArrayBase>::value, @@ -233,7 +287,8 @@ } }; -struct CC_PAINT_EXPORT AnnotateOp final : PaintOp { +class CC_PAINT_EXPORT AnnotateOp final : public PaintOp { + public: enum class AnnotationType { URL, LinkToDestination, @@ -248,13 +303,18 @@ static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); PaintCanvas::AnnotationType annotation_type; SkRect rect; sk_sp<SkData> data; + + private: + AnnotateOp(); }; -struct CC_PAINT_EXPORT ClipPathOp final : PaintOp { +class CC_PAINT_EXPORT ClipPathOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::ClipPath; ClipPathOp(SkPath path, SkClipOp op, bool antialias) : path(path), op(op), antialias(antialias) {} @@ -263,26 +323,36 @@ const SkMatrix& original_ctm); int CountSlowPaths() const; bool HasNonAAPaint() const { return !antialias; } + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafePath path; SkClipOp op; bool antialias; + + private: + ClipPathOp() = default; }; -struct CC_PAINT_EXPORT ClipRectOp final : PaintOp { +class CC_PAINT_EXPORT ClipRectOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::ClipRect; ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias) : rect(rect), op(op), antialias(antialias) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect rect; SkClipOp op; bool antialias; + + private: + ClipRectOp() = default; }; -struct CC_PAINT_EXPORT ClipRRectOp final : PaintOp { +class CC_PAINT_EXPORT ClipRRectOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::ClipRRect; ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias) : rrect(rrect), op(op), antialias(antialias) {} @@ -290,23 +360,33 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasNonAAPaint() const { return !antialias; } + HAS_SERIALIZATION_FUNCTIONS(); SkRRect rrect; SkClipOp op; bool antialias; + + private: + ClipRRectOp() = default; }; -struct CC_PAINT_EXPORT ConcatOp final : PaintOp { +class CC_PAINT_EXPORT ConcatOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Concat; explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; + + private: + ConcatOp() = default; }; -struct CC_PAINT_EXPORT DrawArcOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawArcOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawArc; static constexpr bool kIsDrawOp = true; DrawArcOp(const SkRect& oval, @@ -329,14 +409,19 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect oval; SkScalar start_angle; SkScalar sweep_angle; bool use_center; + + private: + DrawArcOp() = default; }; -struct CC_PAINT_EXPORT DrawCircleOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawCircleOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawCircle; static constexpr bool kIsDrawOp = true; DrawCircleOp(SkScalar cx, @@ -354,25 +439,35 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar cx; SkScalar cy; SkScalar radius; + + private: + DrawCircleOp() = default; }; -struct CC_PAINT_EXPORT DrawColorOp final : PaintOp { +class CC_PAINT_EXPORT DrawColorOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::DrawColor; static constexpr bool kIsDrawOp = true; DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkColor color; SkBlendMode mode; + + private: + DrawColorOp() = default; }; -struct CC_PAINT_EXPORT DrawDRRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawDRRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawDRRect; static constexpr bool kIsDrawOp = true; DrawDRRectOp(const SkRRect& outer, @@ -389,12 +484,17 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRRect outer; SkRRect inner; + + private: + DrawDRRectOp() = default; }; -struct CC_PAINT_EXPORT DrawImageOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawImageOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawImage; static constexpr bool kIsDrawOp = true; DrawImageOp(const PaintImage& image, @@ -414,13 +514,18 @@ const SkMatrix& original_ctm); bool HasDiscardableImages() const; bool HasNonAAPaint() const { return false; } + HAS_SERIALIZATION_FUNCTIONS(); PaintImage image; SkScalar left; SkScalar top; + + private: + DrawImageOp() = default; }; -struct CC_PAINT_EXPORT DrawImageRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawImageRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawImageRect; static constexpr bool kIsDrawOp = true; DrawImageRectOp(const PaintImage& image, @@ -440,14 +545,19 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasDiscardableImages() const; + HAS_SERIALIZATION_FUNCTIONS(); PaintImage image; SkRect src; SkRect dst; PaintCanvas::SrcRectConstraint constraint; + + private: + DrawImageRectOp(); }; -struct CC_PAINT_EXPORT DrawIRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawIRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawIRect; static constexpr bool kIsDrawOp = true; DrawIRectOp(const SkIRect& rect, const PaintFlags& flags) @@ -463,11 +573,16 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasNonAAPaint() const { return false; } + HAS_SERIALIZATION_FUNCTIONS(); SkIRect rect; + + private: + DrawIRectOp() = default; }; -struct CC_PAINT_EXPORT DrawLineOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawLineOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawLine; static constexpr bool kIsDrawOp = true; DrawLineOp(SkScalar x0, @@ -486,6 +601,7 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); int CountSlowPaths() const; @@ -493,9 +609,13 @@ SkScalar y0; SkScalar x1; SkScalar y1; + + private: + DrawLineOp() = default; }; -struct CC_PAINT_EXPORT DrawOvalOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawOvalOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawOval; static constexpr bool kIsDrawOp = true; DrawOvalOp(const SkRect& oval, const PaintFlags& flags) @@ -510,11 +630,16 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect oval; + + private: + DrawOvalOp() = default; }; -struct CC_PAINT_EXPORT DrawPathOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawPathOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawPath; static constexpr bool kIsDrawOp = true; DrawPathOp(const SkPath& path, const PaintFlags& flags) @@ -530,11 +655,16 @@ SkCanvas* canvas, const SkMatrix& original_ctm); int CountSlowPaths() const; + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafePath path; + + private: + DrawPathOp() = default; }; -struct CC_PAINT_EXPORT DrawPosTextOp final : PaintOpWithArray<SkPoint> { +class CC_PAINT_EXPORT DrawPosTextOp final : public PaintOpWithArray<SkPoint> { + public: static constexpr PaintOpType kType = PaintOpType::DrawPosText; static constexpr bool kIsDrawOp = true; DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags); @@ -549,14 +679,19 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); const void* GetData() const { return GetDataForThis(this); } void* GetData() { return GetDataForThis(this); } const SkPoint* GetArray() const { return GetArrayForThis(this); } SkPoint* GetArray() { return GetArrayForThis(this); } + + private: + DrawPosTextOp(); }; -struct CC_PAINT_EXPORT DrawRecordOp final : PaintOp { +class CC_PAINT_EXPORT DrawRecordOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::DrawRecord; static constexpr bool kIsDrawOp = true; explicit DrawRecordOp(sk_sp<const PaintRecord> record); @@ -568,11 +703,16 @@ bool HasDiscardableImages() const; int CountSlowPaths() const; bool HasNonAAPaint() const; + HAS_SERIALIZATION_FUNCTIONS(); sk_sp<const PaintRecord> record; + + private: + DrawRecordOp(); }; -struct CC_PAINT_EXPORT DrawRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawRect; static constexpr bool kIsDrawOp = true; DrawRectOp(const SkRect& rect, const PaintFlags& flags) @@ -587,11 +727,16 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect rect; + + private: + DrawRectOp() = default; }; -struct CC_PAINT_EXPORT DrawRRectOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawRRectOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawRRect; static constexpr bool kIsDrawOp = true; DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags) @@ -606,11 +751,16 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRRect rrect; + + private: + DrawRRectOp() = default; }; -struct CC_PAINT_EXPORT DrawTextOp final : PaintOpWithData { +class CC_PAINT_EXPORT DrawTextOp final : public PaintOpWithData { + public: static constexpr PaintOpType kType = PaintOpType::DrawText; static constexpr bool kIsDrawOp = true; DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags) @@ -625,15 +775,20 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); void* GetData() { return GetDataForThis(this); } const void* GetData() const { return GetDataForThis(this); } SkScalar x; SkScalar y; + + private: + DrawTextOp() = default; }; -struct CC_PAINT_EXPORT DrawTextBlobOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT DrawTextBlobOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::DrawTextBlob; static constexpr bool kIsDrawOp = true; DrawTextBlobOp(sk_sp<SkTextBlob> blob, @@ -651,44 +806,60 @@ const PaintFlags* flags, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); sk_sp<SkTextBlob> blob; SkScalar x; SkScalar y; + + private: + DrawTextBlobOp(); }; -struct CC_PAINT_EXPORT NoopOp final : PaintOp { +class CC_PAINT_EXPORT NoopOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Noop; static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm) {} + HAS_SERIALIZATION_FUNCTIONS(); }; -struct CC_PAINT_EXPORT RestoreOp final : PaintOp { +class CC_PAINT_EXPORT RestoreOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Restore; static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); }; -struct CC_PAINT_EXPORT RotateOp final : PaintOp { +class CC_PAINT_EXPORT RotateOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Rotate; explicit RotateOp(SkScalar degrees) : degrees(degrees) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar degrees; + + private: + RotateOp() = default; }; -struct CC_PAINT_EXPORT SaveOp final : PaintOp { +class CC_PAINT_EXPORT SaveOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Save; static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); }; -struct CC_PAINT_EXPORT SaveLayerOp final : PaintOpWithFlags { +class CC_PAINT_EXPORT SaveLayerOp final : public PaintOpWithFlags { + public: static constexpr PaintOpType kType = PaintOpType::SaveLayer; SaveLayerOp(const SkRect* bounds, const PaintFlags* flags) : PaintOpWithFlags(flags ? *flags : PaintFlags()), @@ -704,11 +875,16 @@ SkCanvas* canvas, const SkMatrix& original_ctm); bool HasNonAAPaint() const { return false; } + HAS_SERIALIZATION_FUNCTIONS(); SkRect bounds; + + private: + SaveLayerOp() = default; }; -struct CC_PAINT_EXPORT SaveLayerAlphaOp final : PaintOp { +class CC_PAINT_EXPORT SaveLayerAlphaOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha; SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha, @@ -719,24 +895,34 @@ static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkRect bounds; uint8_t alpha; bool preserve_lcd_text_requests; + + private: + SaveLayerAlphaOp() = default; }; -struct CC_PAINT_EXPORT ScaleOp final : PaintOp { +class CC_PAINT_EXPORT ScaleOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Scale; ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar sx; SkScalar sy; + + private: + ScaleOp() = default; }; -struct CC_PAINT_EXPORT SetMatrixOp final : PaintOp { +class CC_PAINT_EXPORT SetMatrixOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::SetMatrix; explicit SetMatrixOp(const SkMatrix& matrix) : matrix(matrix) {} // This is the only op that needs the original ctm of the SkCanvas @@ -748,21 +934,32 @@ static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; + + private: + SetMatrixOp() = default; }; -struct CC_PAINT_EXPORT TranslateOp final : PaintOp { +class CC_PAINT_EXPORT TranslateOp final : public PaintOp { + public: static constexpr PaintOpType kType = PaintOpType::Translate; TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {} static void Raster(const PaintOp* op, SkCanvas* canvas, const SkMatrix& original_ctm); + HAS_SERIALIZATION_FUNCTIONS(); SkScalar dx; SkScalar dy; + + private: + TranslateOp() = default; }; +#undef HAS_SERIALIZATION_FUNCTIONS + using LargestPaintOp = DrawDRRectOp; class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 913db86..ac1181ca 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -4,10 +4,12 @@ #include "cc/paint/paint_op_buffer.h" #include "base/memory/ptr_util.h" +#include "base/strings/stringprintf.h" #include "cc/paint/display_item_list.h" #include "cc/test/skia_common.h" #include "cc/test/test_skcanvas.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkWriteBuffer.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" using testing::_; @@ -916,4 +918,1148 @@ buffer.Playback(&canvas); } +std::vector<float> test_floats = {0.f, + 1.f, + -1.f, + 2384.981971f, + 0.0001f, + std::numeric_limits<float>::min(), + std::numeric_limits<float>::max(), + std::numeric_limits<float>::infinity()}; + +std::vector<uint8_t> test_uint8s = { + 0, 255, 128, 10, 45, +}; + +std::vector<SkRect> test_rects = { + SkRect::MakeXYWH(1, 2.5, 3, 4), SkRect::MakeXYWH(0, 0, 0, 0), + SkRect::MakeLargest(), SkRect::MakeXYWH(0.5f, 0.5f, 8.2f, 8.2f), + SkRect::MakeXYWH(-1, -1, 0, 0), SkRect::MakeXYWH(-100, -101, -102, -103)}; + +std::vector<SkRRect> test_rrects = { + SkRRect::MakeEmpty(), SkRRect::MakeOval(SkRect::MakeXYWH(1, 2, 3, 4)), + SkRRect::MakeRect(SkRect::MakeXYWH(-10, 100, 5, 4)), + [] { + SkRRect rrect = SkRRect::MakeEmpty(); + rrect.setNinePatch(SkRect::MakeXYWH(10, 20, 30, 40), 1, 2, 3, 4); + return rrect; + }(), +}; + +std::vector<SkIRect> test_irects = { + SkIRect::MakeXYWH(1, 2, 3, 4), SkIRect::MakeXYWH(0, 0, 0, 0), + SkIRect::MakeLargest(), SkIRect::MakeXYWH(0, 0, 10, 10), + SkIRect::MakeXYWH(-1, -1, 0, 0), SkIRect::MakeXYWH(-100, -101, -102, -103)}; + +std::vector<SkMatrix> test_matrices = { + SkMatrix(), + SkMatrix::MakeScale(3.91f, 4.31f), + SkMatrix::MakeTrans(-5.2f, 8.7f), + [] { + SkMatrix matrix; + SkScalar buffer[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + matrix.set9(buffer); + return matrix; + }(), + [] { + SkMatrix matrix; + SkScalar buffer[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + matrix.set9(buffer); + return matrix; + }(), +}; + +std::vector<SkPath> test_paths = { + [] { + SkPath path; + path.moveTo(SkIntToScalar(20), SkIntToScalar(20)); + path.lineTo(SkIntToScalar(80), SkIntToScalar(20)); + path.lineTo(SkIntToScalar(30), SkIntToScalar(30)); + path.lineTo(SkIntToScalar(20), SkIntToScalar(80)); + return path; + }(), + [] { + SkPath path; + path.addCircle(2, 2, 5); + path.addCircle(3, 4, 2); + path.addArc(SkRect::MakeXYWH(1, 2, 3, 4), 5, 6); + return path; + }(), + SkPath(), +}; + +// TODO(enne): make this more real. +std::vector<PaintFlags> test_flags = { + PaintFlags(), PaintFlags(), PaintFlags(), PaintFlags(), PaintFlags(), +}; + +std::vector<SkColor> test_colors = { + SkColorSetARGBInline(0, 0, 0, 0), + SkColorSetARGBInline(255, 255, 255, 255), + SkColorSetARGBInline(0, 255, 10, 255), + SkColorSetARGBInline(255, 0, 20, 255), + SkColorSetARGBInline(30, 255, 0, 255), + SkColorSetARGBInline(255, 40, 0, 0), +}; + +std::vector<std::string> test_strings = { + "", "foobar", + "blarbideeblarasdfaiousydfp234poiausdofiuapsodfjknla;sdfkjasd;f", +}; + +std::vector<std::vector<SkPoint>> test_point_arrays = { + std::vector<SkPoint>(), + {SkPoint::Make(1, 2)}, + {SkPoint::Make(1, 2), SkPoint::Make(-5.4f, -3.8f)}, + {SkPoint::Make(0, 0), SkPoint::Make(5, 6), SkPoint::Make(-1, -1), + SkPoint::Make(9, 9), SkPoint::Make(50, 50), SkPoint::Make(100, 100)}, +}; + +std::vector<sk_sp<SkTextBlob>> test_blobs = { + [] { + SkPaint font; + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + SkTextBlobBuilder builder; + builder.allocRun(font, 5, 1.2f, 2.3f, &test_rects[0]); + return builder.make(); + }(), + [] { + SkPaint font; + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + SkTextBlobBuilder builder; + builder.allocRun(font, 5, 1.2f, 2.3f, &test_rects[0]); + builder.allocRunPos(font, 16, &test_rects[1]); + builder.allocRunPosH(font, 8, 0, &test_rects[2]); + return builder.make(); + }(), +}; + +// TODO(enne): In practice, probably all paint images need to be uploaded +// ahead of time and not be bitmaps. These paint images should be fake +// gpu resource paint images. +std::vector<PaintImage> test_images = { + PaintImage(PaintImage::GetNextId(), + CreateDiscardableImage(gfx::Size(5, 10))), + PaintImage(PaintImage::GetNextId(), + CreateDiscardableImage(gfx::Size(1, 1))), + PaintImage(PaintImage::GetNextId(), + CreateDiscardableImage(gfx::Size(50, 50))), +}; + +// Writes as many ops in |buffer| as can fit in |output_size| to |output|. +// Records the numbers of bytes written for each op. +class SimpleSerializer { + public: + SimpleSerializer(void* output, size_t output_size) + : current_(static_cast<char*>(output)), + output_size_(output_size), + remaining_(output_size) {} + + void Serialize(const PaintOpBuffer& buffer) { + bytes_written_.resize(buffer.size()); + for (size_t i = 0; i < buffer.size(); ++i) + bytes_written_[i] = 0; + + PaintOp::SerializeOptions options; + + size_t op_idx = 0; + for (const auto* op : PaintOpBuffer::Iterator(&buffer)) { + size_t bytes_written = op->Serialize(current_, remaining_, options); + if (!bytes_written) + return; + + PaintOp* written = reinterpret_cast<PaintOp*>(current_); + EXPECT_EQ(op->GetType(), written->GetType()); + EXPECT_EQ(bytes_written, written->skip); + + bytes_written_[op_idx] = bytes_written; + op_idx++; + current_ += bytes_written; + remaining_ -= bytes_written; + + // Number of bytes bytes_written must be a multiple of PaintOpAlign + // unless the buffer is filled entirely. + if (remaining_ != 0u) + DCHECK_EQ(0u, bytes_written % PaintOpBuffer::PaintOpAlign); + } + } + + const std::vector<size_t>& bytes_written() const { return bytes_written_; } + size_t TotalBytesWritten() const { return output_size_ - remaining_; } + + private: + char* current_ = nullptr; + size_t output_size_ = 0u; + size_t remaining_ = 0u; + std::vector<size_t> bytes_written_; +}; + +class DeserializerIterator { + public: + DeserializerIterator(const void* input, size_t input_size) + : DeserializerIterator(input, + static_cast<const char*>(input), + input_size, + input_size) {} + + DeserializerIterator(DeserializerIterator&&) = default; + DeserializerIterator& operator=(DeserializerIterator&&) = default; + + ~DeserializerIterator() { DestroyDeserializedOp(); } + + DeserializerIterator begin() { + return DeserializerIterator(input_, static_cast<const char*>(input_), + input_size_, input_size_); + } + DeserializerIterator end() { + return DeserializerIterator( + input_, static_cast<const char*>(input_) + input_size_, input_size_, 0); + } + bool operator!=(const DeserializerIterator& other) { + return input_ != other.input_ || current_ != other.current_ || + input_size_ != other.input_size_ || remaining_ != other.remaining_; + } + DeserializerIterator& operator++() { + const PaintOp* serialized = reinterpret_cast<const PaintOp*>(current_); + + CHECK_GE(remaining_, serialized->skip); + current_ += serialized->skip; + remaining_ -= serialized->skip; + + if (remaining_ > 0) + CHECK_GE(remaining_, 4u); + + DeserializeCurrentOp(); + + return *this; + } + + operator bool() const { return remaining_ == 0u; } + const PaintOp* operator->() const { return deserialized_op_; } + const PaintOp* operator*() const { return deserialized_op_; } + + private: + DeserializerIterator(const void* input, + const char* current, + size_t input_size, + size_t remaining) + : input_(input), + current_(current), + input_size_(input_size), + remaining_(remaining) { + DeserializeCurrentOp(); + } + + void DestroyDeserializedOp() { + if (!deserialized_op_) + return; + deserialized_op_->DestroyThis(); + deserialized_op_ = nullptr; + } + + void DeserializeCurrentOp() { + DestroyDeserializedOp(); + + if (!remaining_) + return; + + const PaintOp* serialized = reinterpret_cast<const PaintOp*>(current_); + size_t required = sizeof(LargestPaintOp) + serialized->skip; + + if (data_size_ < required) { + data_.reset(static_cast<char*>( + base::AlignedAlloc(required, PaintOpBuffer::PaintOpAlign))); + data_size_ = required; + } + deserialized_op_ = + PaintOp::Deserialize(current_, remaining_, data_.get(), data_size_); + } + + const void* input_ = nullptr; + const char* current_ = nullptr; + size_t input_size_ = 0u; + size_t remaining_ = 0u; + std::unique_ptr<char, base::AlignedFreeDeleter> data_; + size_t data_size_ = 0u; + PaintOp* deserialized_op_ = nullptr; +}; + +void PushAnnotateOps(PaintOpBuffer* buffer) { + buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::URL, test_rects[0], + SkData::MakeWithCString("thingerdoowhatchamagig")); + // Deliberately test both null and empty SkData. + buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::LINK_TO_DESTINATION, + test_rects[1], nullptr); + buffer->push<AnnotateOp>(PaintCanvas::AnnotationType::NAMED_DESTINATION, + test_rects[2], SkData::MakeEmpty()); +} + +void PushClipPathOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_paths.size(); ++i) { + SkClipOp op = i % 3 ? SkClipOp::kDifference : SkClipOp::kIntersect; + buffer->push<ClipPathOp>(test_paths[i], op, !!(i % 2)); + } +} + +void PushClipRectOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_rects.size(); ++i) { + SkClipOp op = i % 2 ? SkClipOp::kIntersect : SkClipOp::kDifference; + bool antialias = !!(i % 3); + buffer->push<ClipRectOp>(test_rects[i], op, antialias); + } +} + +void PushClipRRectOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_rrects.size(); ++i) { + SkClipOp op = i % 2 ? SkClipOp::kIntersect : SkClipOp::kDifference; + bool antialias = !!(i % 3); + buffer->push<ClipRRectOp>(test_rrects[i], op, antialias); + } +} + +void PushConcatOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_matrices.size(); ++i) + buffer->push<ConcatOp>(test_matrices[i]); +} + +void PushDrawArcOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_floats.size() - 1, test_flags.size()), + test_rects.size()); + for (size_t i = 0; i < len; ++i) { + bool use_center = !!(i % 2); + buffer->push<DrawArcOp>(test_rects[i], test_floats[i], test_floats[i + 1], + use_center, test_flags[i]); + } +} + +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)); + } +} + +void PushDrawDRRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_rrects.size() - 1, test_flags.size()); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawDRRectOp>(test_rrects[i], test_rrects[i + 1], + test_flags[i]); + } +} + +void PushDrawImageOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_images.size(), test_flags.size()), + test_floats.size() - 1); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawImageOp>(test_images[i], test_floats[i], + test_floats[i + 1], &test_flags[i]); + } + + // Test optional flags + // TODO(enne): maybe all these optional ops should not be optional. + buffer->push<DrawImageOp>(test_images[0], test_floats[0], test_floats[1], + nullptr); +} + +void PushDrawImageRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_images.size(), test_flags.size()), + test_rects.size() - 1); + for (size_t i = 0; i < len; ++i) { + PaintCanvas::SrcRectConstraint constraint = + i % 2 ? PaintCanvas::kStrict_SrcRectConstraint + : PaintCanvas::kFast_SrcRectConstraint; + buffer->push<DrawImageRectOp>(test_images[i], test_rects[i], + test_rects[i + 1], &test_flags[i], + constraint); + } + + // Test optional flags. + buffer->push<DrawImageRectOp>(test_images[0], test_rects[0], test_rects[1], + nullptr, + PaintCanvas::kStrict_SrcRectConstraint); +} + +void PushDrawIRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_irects.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawIRectOp>(test_irects[i], test_flags[i]); +} + +void PushDrawLineOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_floats.size() - 3, test_flags.size()); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawLineOp>(test_floats[i], test_floats[i + 1], + test_floats[i + 2], test_floats[i + 3], + test_flags[i]); + } +} + +void PushDrawOvalOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_paths.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawOvalOp>(test_rects[i], test_flags[i]); +} + +void PushDrawPathOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_paths.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawPathOp>(test_paths[i], test_flags[i]); +} + +void PushDrawPosTextOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_flags.size(), test_strings.size()), + test_point_arrays.size()); + for (size_t i = 0; i < len; ++i) { + // Make sure empty array works fine. + SkPoint* array = + test_point_arrays[i].size() > 0 ? &test_point_arrays[i][0] : nullptr; + buffer->push_with_array<DrawPosTextOp>( + test_strings[i].c_str(), test_strings[i].size() + 1, array, + test_point_arrays[i].size(), test_flags[i]); + } +} + +void PushDrawRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_rects.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawRectOp>(test_rects[i], test_flags[i]); +} + +void PushDrawRRectOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_rrects.size(), test_flags.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<DrawRRectOp>(test_rrects[i], test_flags[i]); +} + +void PushDrawTextOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_strings.size(), test_flags.size()), + test_floats.size() - 1); + for (size_t i = 0; i < len; ++i) { + buffer->push_with_data<DrawTextOp>( + test_strings[i].c_str(), test_strings[i].size() + 1, test_floats[i], + test_floats[i + 1], test_flags[i]); + } +} + +void PushDrawTextBlobOps(PaintOpBuffer* buffer) { + size_t len = std::min(std::min(test_blobs.size(), test_flags.size()), + test_floats.size() - 1); + for (size_t i = 0; i < len; ++i) { + buffer->push<DrawTextBlobOp>(test_blobs[i], test_floats[i], + test_floats[i + 1], test_flags[i]); + } +} + +void PushNoopOps(PaintOpBuffer* buffer) { + buffer->push<NoopOp>(); + buffer->push<NoopOp>(); + buffer->push<NoopOp>(); + buffer->push<NoopOp>(); +} + +void PushRestoreOps(PaintOpBuffer* buffer) { + buffer->push<RestoreOp>(); + buffer->push<RestoreOp>(); + buffer->push<RestoreOp>(); + buffer->push<RestoreOp>(); +} + +void PushRotateOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_floats.size(); ++i) + buffer->push<RotateOp>(test_floats[i]); +} + +void PushSaveOps(PaintOpBuffer* buffer) { + buffer->push<SaveOp>(); + buffer->push<SaveOp>(); + buffer->push<SaveOp>(); + buffer->push<SaveOp>(); +} + +void PushSaveLayerOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_flags.size(), test_rects.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<SaveLayerOp>(&test_rects[i], &test_flags[i]); + + // Test combinations of optional args. + buffer->push<SaveLayerOp>(nullptr, &test_flags[0]); + buffer->push<SaveLayerOp>(&test_rects[0], nullptr); + buffer->push<SaveLayerOp>(nullptr, nullptr); +} + +void PushSaveLayerAlphaOps(PaintOpBuffer* buffer) { + size_t len = std::min(test_uint8s.size(), test_rects.size()); + for (size_t i = 0; i < len; ++i) + buffer->push<SaveLayerAlphaOp>(&test_rects[i], test_uint8s[i], !!(i % 2)); + + // Test optional args. + buffer->push<SaveLayerAlphaOp>(nullptr, test_uint8s[0], false); +} + +void PushScaleOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_floats.size(); i += 2) + buffer->push<ScaleOp>(test_floats[i], test_floats[i + 1]); +} + +void PushSetMatrixOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_matrices.size(); ++i) + buffer->push<SetMatrixOp>(test_matrices[i]); +} + +void PushTranslateOps(PaintOpBuffer* buffer) { + for (size_t i = 0; i < test_floats.size(); i += 2) + buffer->push<TranslateOp>(test_floats[i], test_floats[i + 1]); +} + +void CompareFlags(const PaintFlags& original, const PaintFlags& written) {} + +void CompareImages(const PaintImage& original, const PaintImage& written) {} + +void CompareAnnotateOp(const AnnotateOp* original, const AnnotateOp* written) { + EXPECT_EQ(original->annotation_type, written->annotation_type); + EXPECT_EQ(original->rect, written->rect); + EXPECT_EQ(!!original->data, !!written->data); + if (original->data) { + EXPECT_EQ(original->data->size(), written->data->size()); + EXPECT_EQ(0, memcmp(original->data->data(), written->data->data(), + written->data->size())); + } +} + +void CompareClipPathOp(const ClipPathOp* original, const ClipPathOp* written) { + EXPECT_TRUE(original->path == written->path); + EXPECT_EQ(original->op, written->op); + EXPECT_EQ(original->antialias, written->antialias); +} + +void CompareClipRectOp(const ClipRectOp* original, const ClipRectOp* written) { + EXPECT_EQ(original->rect, written->rect); + EXPECT_EQ(original->op, written->op); + EXPECT_EQ(original->antialias, written->antialias); +} + +void CompareClipRRectOp(const ClipRRectOp* original, + const ClipRRectOp* written) { + EXPECT_EQ(original->rrect, written->rrect); + EXPECT_EQ(original->op, written->op); + EXPECT_EQ(original->antialias, written->antialias); +} + +void CompareConcatOp(const ConcatOp* original, const ConcatOp* written) { + EXPECT_EQ(original->matrix, written->matrix); + EXPECT_EQ(original->matrix.getType(), written->matrix.getType()); +} + +void CompareDrawArcOp(const DrawArcOp* original, const DrawArcOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->oval, written->oval); + EXPECT_EQ(original->start_angle, written->start_angle); + EXPECT_EQ(original->sweep_angle, written->sweep_angle); + EXPECT_EQ(original->use_center, written->use_center); +} + +void CompareDrawCircleOp(const DrawCircleOp* original, + const DrawCircleOp* written) { + 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_EQ(original->color, written->color); +} + +void CompareDrawDRRectOp(const DrawDRRectOp* original, + const DrawDRRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->outer, written->outer); + EXPECT_EQ(original->inner, written->inner); +} + +void CompareDrawImageOp(const DrawImageOp* original, + const DrawImageOp* written) { + CompareFlags(original->flags, written->flags); + CompareImages(original->image, written->image); + EXPECT_EQ(original->left, written->left); + EXPECT_EQ(original->top, written->top); +} + +void CompareDrawImageRectOp(const DrawImageRectOp* original, + const DrawImageRectOp* written) { + CompareFlags(original->flags, written->flags); + CompareImages(original->image, written->image); + EXPECT_EQ(original->src, written->src); + EXPECT_EQ(original->dst, written->dst); +} + +void CompareDrawIRectOp(const DrawIRectOp* original, + const DrawIRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->rect, written->rect); +} + +void CompareDrawLineOp(const DrawLineOp* original, const DrawLineOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->x0, written->x0); + EXPECT_EQ(original->y0, written->y0); + EXPECT_EQ(original->x1, written->x1); + EXPECT_EQ(original->y1, written->y1); +} + +void CompareDrawOvalOp(const DrawOvalOp* original, const DrawOvalOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->oval, written->oval); +} + +void CompareDrawPathOp(const DrawPathOp* original, const DrawPathOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_TRUE(original->path == written->path); +} + +void CompareDrawPosTextOp(const DrawPosTextOp* original, + const DrawPosTextOp* written) { + CompareFlags(original->flags, written->flags); + ASSERT_EQ(original->bytes, written->bytes); + EXPECT_EQ(std::string(static_cast<const char*>(original->GetData())), + std::string(static_cast<const char*>(written->GetData()))); + ASSERT_EQ(original->count, written->count); + for (size_t i = 0; i < original->count; ++i) + EXPECT_EQ(original->GetArray()[i], written->GetArray()[i]); +} + +void CompareDrawRectOp(const DrawRectOp* original, const DrawRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->rect, written->rect); +} + +void CompareDrawRRectOp(const DrawRRectOp* original, + const DrawRRectOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->rrect, written->rrect); +} + +void CompareDrawTextOp(const DrawTextOp* original, const DrawTextOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->x, written->x); + EXPECT_EQ(original->y, written->y); + ASSERT_EQ(original->bytes, written->bytes); + EXPECT_EQ(std::string(static_cast<const char*>(original->GetData())), + std::string(static_cast<const char*>(written->GetData()))); +} + +void CompareDrawTextBlobOp(const DrawTextBlobOp* original, + const DrawTextBlobOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->x, written->x); + EXPECT_EQ(original->y, written->y); + + // TODO(enne): implement SkTextBlob serialization: http://crbug.com/737629 + if (!original->blob || !written->blob) + return; + + ASSERT_TRUE(original->blob); + ASSERT_TRUE(written->blob); + + // No text blob operator==, so flatten them both and compare. + size_t max_size = original->skip; + + std::vector<char> original_mem; + original_mem.resize(max_size); + SkBinaryWriteBuffer original_flattened(&original_mem[0], max_size); + original->blob->flatten(original_flattened); + original_mem.resize(original_flattened.bytesWritten()); + + std::vector<char> written_mem; + written_mem.resize(max_size); + SkBinaryWriteBuffer written_flattened(&written_mem[0], max_size); + written->blob->flatten(written_flattened); + written_mem.resize(written_flattened.bytesWritten()); + + ASSERT_EQ(original_mem.size(), written_mem.size()); + EXPECT_EQ(original_mem, written_mem); +} + +void CompareNoopOp(const NoopOp* original, const NoopOp* written) { + // Nothing to compare. +} + +void CompareRestoreOp(const RestoreOp* original, const RestoreOp* written) { + // Nothing to compare. +} + +void CompareRotateOp(const RotateOp* original, const RotateOp* written) { + EXPECT_EQ(original->degrees, written->degrees); +} + +void CompareSaveOp(const SaveOp* original, const SaveOp* written) { + // Nothing to compare. +} + +void CompareSaveLayerOp(const SaveLayerOp* original, + const SaveLayerOp* written) { + CompareFlags(original->flags, written->flags); + EXPECT_EQ(original->bounds, written->bounds); +} + +void CompareSaveLayerAlphaOp(const SaveLayerAlphaOp* original, + const SaveLayerAlphaOp* written) { + EXPECT_EQ(original->bounds, written->bounds); + EXPECT_EQ(original->alpha, written->alpha); + EXPECT_EQ(original->preserve_lcd_text_requests, + written->preserve_lcd_text_requests); +} + +void CompareScaleOp(const ScaleOp* original, const ScaleOp* written) { + EXPECT_EQ(original->sx, written->sx); + EXPECT_EQ(original->sy, written->sy); +} + +void CompareSetMatrixOp(const SetMatrixOp* original, + const SetMatrixOp* written) { + EXPECT_EQ(original->matrix, written->matrix); +} + +void CompareTranslateOp(const TranslateOp* original, + const TranslateOp* written) { + EXPECT_EQ(original->dx, written->dx); + EXPECT_EQ(original->dy, written->dy); +} + +class PaintOpSerializationTest : public ::testing::TestWithParam<uint8_t> { + public: + PaintOpType GetParamType() const { + return static_cast<PaintOpType>(GetParam()); + } + + void PushTestOps(PaintOpType type) { + switch (type) { + case PaintOpType::Annotate: + PushAnnotateOps(&buffer_); + break; + case PaintOpType::ClipPath: + PushClipPathOps(&buffer_); + break; + case PaintOpType::ClipRect: + PushClipRectOps(&buffer_); + break; + case PaintOpType::ClipRRect: + PushClipRRectOps(&buffer_); + break; + case PaintOpType::Concat: + PushConcatOps(&buffer_); + break; + case PaintOpType::DrawArc: + PushDrawArcOps(&buffer_); + break; + case PaintOpType::DrawCircle: + PushDrawCircleOps(&buffer_); + break; + case PaintOpType::DrawColor: + PushDrawColorOps(&buffer_); + break; + case PaintOpType::DrawDRRect: + PushDrawDRRectOps(&buffer_); + break; + case PaintOpType::DrawImage: + PushDrawImageOps(&buffer_); + break; + case PaintOpType::DrawImageRect: + PushDrawImageRectOps(&buffer_); + break; + case PaintOpType::DrawIRect: + PushDrawIRectOps(&buffer_); + break; + case PaintOpType::DrawLine: + PushDrawLineOps(&buffer_); + break; + case PaintOpType::DrawOval: + PushDrawOvalOps(&buffer_); + break; + case PaintOpType::DrawPath: + PushDrawPathOps(&buffer_); + break; + case PaintOpType::DrawPosText: + PushDrawPosTextOps(&buffer_); + break; + case PaintOpType::DrawRecord: + // Not supported. + break; + case PaintOpType::DrawRect: + PushDrawRectOps(&buffer_); + break; + case PaintOpType::DrawRRect: + PushDrawRRectOps(&buffer_); + break; + case PaintOpType::DrawText: + PushDrawTextOps(&buffer_); + break; + case PaintOpType::DrawTextBlob: + PushDrawTextBlobOps(&buffer_); + break; + case PaintOpType::Noop: + PushNoopOps(&buffer_); + break; + case PaintOpType::Restore: + PushRestoreOps(&buffer_); + break; + case PaintOpType::Rotate: + PushRotateOps(&buffer_); + break; + case PaintOpType::Save: + PushSaveOps(&buffer_); + break; + case PaintOpType::SaveLayer: + PushSaveLayerOps(&buffer_); + break; + case PaintOpType::SaveLayerAlpha: + PushSaveLayerAlphaOps(&buffer_); + break; + case PaintOpType::Scale: + PushScaleOps(&buffer_); + break; + case PaintOpType::SetMatrix: + PushSetMatrixOps(&buffer_); + break; + case PaintOpType::Translate: + PushTranslateOps(&buffer_); + break; + } + } + + static void ExpectOpsEqual(const PaintOp* original, const PaintOp* written) { + ASSERT_TRUE(original); + ASSERT_TRUE(written); + ASSERT_EQ(original->GetType(), written->GetType()); + EXPECT_EQ(original->skip, written->skip); + + switch (original->GetType()) { + case PaintOpType::Annotate: + CompareAnnotateOp(static_cast<const AnnotateOp*>(original), + static_cast<const AnnotateOp*>(written)); + break; + case PaintOpType::ClipPath: + CompareClipPathOp(static_cast<const ClipPathOp*>(original), + static_cast<const ClipPathOp*>(written)); + break; + case PaintOpType::ClipRect: + CompareClipRectOp(static_cast<const ClipRectOp*>(original), + static_cast<const ClipRectOp*>(written)); + break; + case PaintOpType::ClipRRect: + CompareClipRRectOp(static_cast<const ClipRRectOp*>(original), + static_cast<const ClipRRectOp*>(written)); + break; + case PaintOpType::Concat: + CompareConcatOp(static_cast<const ConcatOp*>(original), + static_cast<const ConcatOp*>(written)); + break; + case PaintOpType::DrawArc: + 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)); + break; + case PaintOpType::DrawDRRect: + CompareDrawDRRectOp(static_cast<const DrawDRRectOp*>(original), + static_cast<const DrawDRRectOp*>(written)); + break; + case PaintOpType::DrawImage: + CompareDrawImageOp(static_cast<const DrawImageOp*>(original), + static_cast<const DrawImageOp*>(written)); + break; + case PaintOpType::DrawImageRect: + CompareDrawImageRectOp(static_cast<const DrawImageRectOp*>(original), + static_cast<const DrawImageRectOp*>(written)); + break; + case PaintOpType::DrawIRect: + CompareDrawIRectOp(static_cast<const DrawIRectOp*>(original), + static_cast<const DrawIRectOp*>(written)); + break; + case PaintOpType::DrawLine: + CompareDrawLineOp(static_cast<const DrawLineOp*>(original), + static_cast<const DrawLineOp*>(written)); + break; + case PaintOpType::DrawOval: + CompareDrawOvalOp(static_cast<const DrawOvalOp*>(original), + static_cast<const DrawOvalOp*>(written)); + break; + case PaintOpType::DrawPath: + CompareDrawPathOp(static_cast<const DrawPathOp*>(original), + static_cast<const DrawPathOp*>(written)); + break; + case PaintOpType::DrawPosText: + CompareDrawPosTextOp(static_cast<const DrawPosTextOp*>(original), + static_cast<const DrawPosTextOp*>(written)); + break; + case PaintOpType::DrawRecord: + // Not supported. + break; + case PaintOpType::DrawRect: + CompareDrawRectOp(static_cast<const DrawRectOp*>(original), + static_cast<const DrawRectOp*>(written)); + break; + case PaintOpType::DrawRRect: + CompareDrawRRectOp(static_cast<const DrawRRectOp*>(original), + static_cast<const DrawRRectOp*>(written)); + break; + case PaintOpType::DrawText: + CompareDrawTextOp(static_cast<const DrawTextOp*>(original), + static_cast<const DrawTextOp*>(written)); + break; + case PaintOpType::DrawTextBlob: + CompareDrawTextBlobOp(static_cast<const DrawTextBlobOp*>(original), + static_cast<const DrawTextBlobOp*>(written)); + break; + case PaintOpType::Noop: + CompareNoopOp(static_cast<const NoopOp*>(original), + static_cast<const NoopOp*>(written)); + break; + case PaintOpType::Restore: + CompareRestoreOp(static_cast<const RestoreOp*>(original), + static_cast<const RestoreOp*>(written)); + break; + case PaintOpType::Rotate: + CompareRotateOp(static_cast<const RotateOp*>(original), + static_cast<const RotateOp*>(written)); + break; + case PaintOpType::Save: + CompareSaveOp(static_cast<const SaveOp*>(original), + static_cast<const SaveOp*>(written)); + break; + case PaintOpType::SaveLayer: + CompareSaveLayerOp(static_cast<const SaveLayerOp*>(original), + static_cast<const SaveLayerOp*>(written)); + break; + case PaintOpType::SaveLayerAlpha: + CompareSaveLayerAlphaOp(static_cast<const SaveLayerAlphaOp*>(original), + static_cast<const SaveLayerAlphaOp*>(written)); + break; + case PaintOpType::Scale: + CompareScaleOp(static_cast<const ScaleOp*>(original), + static_cast<const ScaleOp*>(written)); + break; + case PaintOpType::SetMatrix: + CompareSetMatrixOp(static_cast<const SetMatrixOp*>(original), + static_cast<const SetMatrixOp*>(written)); + break; + case PaintOpType::Translate: + CompareTranslateOp(static_cast<const TranslateOp*>(original), + static_cast<const TranslateOp*>(written)); + break; + } + } + + void ResizeOutputBuffer() { + // An arbitrary deserialization buffer size that should fit all the ops + // in the buffer_. + output_size_ = (100 + sizeof(LargestPaintOp)) * buffer_.size(); + output_.reset(static_cast<char*>( + base::AlignedAlloc(output_size_, PaintOpBuffer::PaintOpAlign))); + } + + bool IsTypeSupported() { + // DrawRecordOps must be flattened and are not currently serialized. + // All other types must push non-zero amounts of ops in PushTestOps. + return GetParamType() != PaintOpType::DrawRecord; + } + + protected: + std::unique_ptr<char, base::AlignedFreeDeleter> output_; + size_t output_size_ = 0u; + PaintOpBuffer buffer_; +}; + +INSTANTIATE_TEST_CASE_P( + P, + PaintOpSerializationTest, + ::testing::Range(static_cast<uint8_t>(0), + static_cast<uint8_t>(PaintOpType::LastPaintOpType))); + +// Test serializing and then deserializing all test ops. They should all +// write successfully and be identical to the original ops in the buffer. +TEST_P(PaintOpSerializationTest, SmokeTest) { + if (!IsTypeSupported()) + return; + + PushTestOps(GetParamType()); + + ResizeOutputBuffer(); + + SimpleSerializer serializer(output_.get(), output_size_); + serializer.Serialize(buffer_); + + // Expect all ops to write more than 0 bytes. + for (size_t i = 0; i < buffer_.size(); ++i) { + SCOPED_TRACE(base::StringPrintf( + "%s #%zd", PaintOpTypeToString(GetParamType()).c_str(), i)); + EXPECT_GT(serializer.bytes_written()[i], 0u); + } + + PaintOpBuffer::Iterator iter(&buffer_); + for (auto* base_written : + DeserializerIterator(output_.get(), serializer.TotalBytesWritten())) { + SCOPED_TRACE(base::StringPrintf( + "%s #%zd", PaintOpTypeToString(GetParamType()).c_str(), iter.op_idx())); + ExpectOpsEqual(*iter, base_written); + ++iter; + } + + EXPECT_EQ(buffer_.size(), iter.op_idx()); +} + +// Verify for all test ops that serializing into a smaller size aborts +// correctly and doesn't write anything. +TEST_P(PaintOpSerializationTest, SerializationFailures) { + if (!IsTypeSupported()) + return; + + PushTestOps(GetParamType()); + + ResizeOutputBuffer(); + + SimpleSerializer serializer(output_.get(), output_size_); + serializer.Serialize(buffer_); + std::vector<size_t> bytes_written = serializer.bytes_written(); + + PaintOp::SerializeOptions options; + + for (PaintOpBuffer::Iterator iter(&buffer_); iter; ++iter) { + SCOPED_TRACE(base::StringPrintf( + "%s #%zd", PaintOpTypeToString(GetParamType()).c_str(), iter.op_idx())); + size_t expected_bytes = bytes_written[iter.op_idx()]; + EXPECT_GT(expected_bytes, 0u); + + // Attempt to write op into a buffer of size |i|, and only expect + // it to succeed if the buffer is large enough. + for (size_t i = 0; i < bytes_written[iter.op_idx()] + 2; ++i) { + size_t written_bytes = iter->Serialize(output_.get(), i, options); + if (i >= expected_bytes) { + EXPECT_EQ(expected_bytes, written_bytes) << "i: " << i; + } else { + EXPECT_EQ(0u, written_bytes) << "i: " << i; + } + } + } +} + +// Verify that deserializing test ops from too small buffers aborts +// correctly, in case the deserialized data is lying about how big it is. +TEST_P(PaintOpSerializationTest, DeserializationFailures) { + if (!IsTypeSupported()) + return; + + PushTestOps(GetParamType()); + + ResizeOutputBuffer(); + + SimpleSerializer serializer(output_.get(), output_size_); + serializer.Serialize(buffer_); + + char* current = static_cast<char*>(output_.get()); + + static constexpr size_t kAlign = PaintOpBuffer::PaintOpAlign; + static constexpr size_t kOutputOpSize = sizeof(LargestPaintOp) + 100; + std::unique_ptr<char, base::AlignedFreeDeleter> deserialize_buffer_( + static_cast<char*>(base::AlignedAlloc(kOutputOpSize, kAlign))); + + for (PaintOpBuffer::Iterator iter(&buffer_); iter; ++iter) { + PaintOp* serialized = reinterpret_cast<PaintOp*>(current); + uint32_t skip = serialized->skip; + + // Read from buffers of various sizes to make sure that having a serialized + // op size that is larger than the input buffer provided causes a + // deserialization failure to return nullptr. Also test a few valid sizes + // larger than read size. + for (size_t read_size = 0; read_size < skip + kAlign * 2 + 2; ++read_size) { + SCOPED_TRACE( + base::StringPrintf("%s #%zd, read_size: %zd", + PaintOpTypeToString(GetParamType()).c_str(), + iter.op_idx(), read_size)); + // Because PaintOp::Deserialize early outs when the input size is < skip + // deliberately lie about the skip. This op tooooootally fits. + // This will verify that individual op deserializing code behaves + // properly when presented with invalid offsets. + serialized->skip = read_size; + PaintOp* written = PaintOp::Deserialize( + current, read_size, deserialize_buffer_.get(), kOutputOpSize); + + // Skips are only valid if they are aligned. + if (read_size >= skip && read_size % kAlign == 0) { + ASSERT_NE(nullptr, written); + ASSERT_LE(written->skip, kOutputOpSize); + EXPECT_EQ(GetParamType(), written->GetType()); + } else { + EXPECT_EQ(nullptr, written); + } + + if (written) + written->DestroyThis(); + } + + current += skip; + } +} + +// Test generic PaintOp deserializing failure cases. +TEST(PaintOpBufferTest, PaintOpDeserialize) { + static constexpr size_t kSize = sizeof(LargestPaintOp) + 100; + static constexpr size_t kAlign = PaintOpBuffer::PaintOpAlign; + std::unique_ptr<char, base::AlignedFreeDeleter> input_( + static_cast<char*>(base::AlignedAlloc(kSize, kAlign))); + std::unique_ptr<char, base::AlignedFreeDeleter> output_( + static_cast<char*>(base::AlignedAlloc(kSize, kAlign))); + + PaintOpBuffer buffer; + buffer.push<DrawColorOp>(SK_ColorMAGENTA, SkBlendMode::kSrc); + + PaintOpBuffer::Iterator iter(&buffer); + PaintOp* op = *iter; + ASSERT_TRUE(op); + + PaintOp::SerializeOptions options; + size_t bytes_written = op->Serialize(input_.get(), kSize, options); + ASSERT_GT(bytes_written, 0u); + + // can deserialize from exactly the right size + PaintOp* success = + PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize); + ASSERT_TRUE(success); + success->DestroyThis(); + + // fail to deserialize if skip goes past input size + // (the DeserializationFailures test above tests if the skip is lying) + for (size_t i = 0; i < bytes_written - 1; ++i) + EXPECT_FALSE(PaintOp::Deserialize(input_.get(), i, output_.get(), kSize)); + + // unaligned skips fail to deserialize + PaintOp* serialized = reinterpret_cast<PaintOp*>(input_.get()); + EXPECT_EQ(0u, serialized->skip % kAlign); + serialized->skip -= 1; + EXPECT_FALSE( + PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize)); + serialized->skip += 1; + + // bogus types fail to deserialize + serialized->type = static_cast<uint8_t>(PaintOpType::LastPaintOpType) + 1; + EXPECT_FALSE( + PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize)); +} + } // namespace cc
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc new file mode 100644 index 0000000..6428d4c7 --- /dev/null +++ b/cc/paint/paint_op_reader.cc
@@ -0,0 +1,128 @@ +// 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 "cc/paint/paint_op_reader.h" + +#include <stddef.h> + +#include "cc/paint/paint_flags.h" +#include "third_party/skia/include/core/SkPath.h" +#include "third_party/skia/include/core/SkRRect.h" +#include "third_party/skia/include/core/SkTextBlob.h" + +namespace cc { + +template <typename T> +void PaintOpReader::ReadSimple(T* val) { + if (remaining_bytes_ < sizeof(T)) + valid_ = false; + if (!valid_) + return; + + *val = reinterpret_cast<const T*>(memory_)[0]; + + memory_ += sizeof(T); + remaining_bytes_ -= sizeof(T); +} + +void PaintOpReader::ReadData(size_t bytes, void* data) { + if (remaining_bytes_ < bytes) + valid_ = false; + if (!valid_) + return; + + memcpy(data, memory_, bytes); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpReader::ReadArray(size_t count, SkPoint* array) { + size_t bytes = count * sizeof(SkPoint); + if (remaining_bytes_ < bytes) + valid_ = false; + // Overflow? + if (count > static_cast<size_t>(~0) / sizeof(SkPoint)) + valid_ = false; + if (!valid_) + return; + + memcpy(array, memory_, bytes); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpReader::Read(SkScalar* data) { + ReadSimple(data); +} + +void PaintOpReader::Read(size_t* data) { + ReadSimple(data); +} + +void PaintOpReader::Read(uint8_t* data) { + ReadSimple(data); +} + +void PaintOpReader::Read(SkRect* rect) { + ReadSimple(rect); +} + +void PaintOpReader::Read(SkIRect* rect) { + ReadSimple(rect); +} + +void PaintOpReader::Read(SkRRect* rect) { + ReadSimple(rect); +} + +void PaintOpReader::Read(SkPath* path) { + if (!valid_) + return; + + // TODO(enne): Should the writer write how many bytes it expects as well? + size_t read_bytes = path->readFromMemory(memory_, remaining_bytes_); + if (!read_bytes) + valid_ = false; + + memory_ += read_bytes; + remaining_bytes_ -= read_bytes; +} + +void PaintOpReader::Read(PaintFlags* flags) { + // TODO(enne): implement PaintFlags serialization: http://crbug.com/737629 +} + +void PaintOpReader::Read(PaintImage* image) { + // TODO(enne): implement PaintImage serialization: http://crbug.com/737629 +} + +void PaintOpReader::Read(sk_sp<SkData>* data) { + // Clobber any garbage. + + size_t bytes; + ReadSimple(&bytes); + if (remaining_bytes_ < bytes) + valid_ = false; + if (!valid_) + return; + + // Separate out empty vs not valid cases. + if (bytes == 0) { + bool has_data = false; + Read(&has_data); + if (has_data) + *data = SkData::MakeEmpty(); + return; + } + *data = SkData::MakeWithCopy(memory_, bytes); + + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpReader::Read(sk_sp<SkTextBlob>* blob) { + // TODO(enne): implement SkTextBlob serialization: http://crbug.com/737629 +} + +} // namespace cc
diff --git a/cc/paint/paint_op_reader.h b/cc/paint/paint_op_reader.h new file mode 100644 index 0000000..0252178 --- /dev/null +++ b/cc/paint/paint_op_reader.h
@@ -0,0 +1,76 @@ +// 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 CC_PAINT_PAINT_OP_READER_H_ +#define CC_PAINT_PAINT_OP_READER_H_ + +#include <vector> + +#include "cc/paint/paint_op_writer.h" + +namespace cc { + +// PaintOpReader takes garbage |memory| and clobbers it with successive +// read functions. +class PaintOpReader { + public: + PaintOpReader(const void* memory, size_t size) + : memory_(static_cast<const char*>(memory) + + PaintOpWriter::HeaderBytes()), + remaining_bytes_(size - PaintOpWriter::HeaderBytes()) { + if (size < PaintOpWriter::HeaderBytes()) + valid_ = false; + } + + bool valid() const { return valid_; } + + void ReadData(size_t bytes, void* data); + void ReadArray(size_t count, SkPoint* array); + + void Read(SkScalar* data); + void Read(size_t* data); + void Read(uint8_t* data); + void Read(SkRect* rect); + void Read(SkIRect* rect); + void Read(SkRRect* rect); + + void Read(SkPath* path); + void Read(PaintFlags* flags); + void Read(PaintImage* image); + void Read(sk_sp<SkData>* data); + void Read(sk_sp<SkTextBlob>* blob); + + void Read(SkClipOp* op) { + uint8_t value = 0u; + Read(&value); + *op = static_cast<SkClipOp>(value); + } + void Read(PaintCanvas::AnnotationType* type) { + uint8_t value = 0u; + Read(&value); + *type = static_cast<PaintCanvas::AnnotationType>(value); + } + void Read(PaintCanvas::SrcRectConstraint* constraint) { + uint8_t value = 0u; + Read(&value); + *constraint = static_cast<PaintCanvas::SrcRectConstraint>(value); + } + void Read(bool* data) { + uint8_t value = 0u; + Read(&value); + *data = !!value; + } + + private: + template <typename T> + void ReadSimple(T* val); + + const char* memory_ = nullptr; + size_t remaining_bytes_ = 0u; + bool valid_ = true; +}; + +} // namespace cc + +#endif // CC_PAINT_PAINT_OP_READER_H_
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc new file mode 100644 index 0000000..1248e17 --- /dev/null +++ b/cc/paint/paint_op_writer.cc
@@ -0,0 +1,104 @@ +// 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 "cc/paint/paint_op_writer.h" + +#include "cc/paint/paint_flags.h" +#include "third_party/skia/include/core/SkTextBlob.h" + +namespace cc { + +template <typename T> +void PaintOpWriter::WriteSimple(const T& val) { + static_assert(base::is_trivially_copyable<T>::value, ""); + if (sizeof(T) > remaining_bytes_) + valid_ = false; + if (!valid_) + return; + + reinterpret_cast<T*>(memory_)[0] = val; + + memory_ += sizeof(T); + remaining_bytes_ -= sizeof(T); +} + +void PaintOpWriter::Write(size_t data) { + WriteSimple(data); +} + +void PaintOpWriter::Write(SkScalar data) { + WriteSimple(data); +} + +void PaintOpWriter::Write(uint8_t data) { + WriteSimple(data); +} + +void PaintOpWriter::Write(const SkRect& rect) { + WriteSimple(rect); +} + +void PaintOpWriter::Write(const SkIRect& rect) { + WriteSimple(rect); +} + +void PaintOpWriter::Write(const SkRRect& rect) { + WriteSimple(rect); +} + +void PaintOpWriter::Write(const SkPath& path) { + size_t bytes = path.writeToMemory(nullptr); + if (bytes > remaining_bytes_) + valid_ = false; + if (!valid_) + return; + + path.writeToMemory(memory_); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpWriter::Write(const PaintFlags& flags) { + // TODO(enne): implement PaintFlags serialization: http://crbug.com/737629 +} + +void PaintOpWriter::Write(const PaintImage& image, ImageDecodeCache* cache) { + // TODO(enne): implement PaintImage serialization: http://crbug.com/737629 +} + +void PaintOpWriter::Write(const sk_sp<SkData>& data) { + if (data.get() && data->size()) { + Write(data->size()); + WriteData(data->size(), data->data()); + } else { + // Differentiate between nullptr and valid but zero size. It's not clear + // that this happens in practice, but seems better to be consistent. + Write(static_cast<size_t>(0)); + Write(!!data.get()); + } +} + +void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) { + // TODO(enne): implement SkTextBlob serialization: http://crbug.com/737629 +} + +void PaintOpWriter::WriteData(size_t bytes, const void* input) { + if (bytes > remaining_bytes_) + valid_ = false; + if (!valid_) + return; + if (bytes == 0) + return; + + memcpy(memory_, input, bytes); + memory_ += bytes; + remaining_bytes_ -= bytes; +} + +void PaintOpWriter::WriteArray(size_t count, const SkPoint* input) { + size_t bytes = sizeof(SkPoint) * count; + WriteData(bytes, input); +} + +} // namespace cc
diff --git a/cc/paint/paint_op_writer.h b/cc/paint/paint_op_writer.h new file mode 100644 index 0000000..0163067f --- /dev/null +++ b/cc/paint/paint_op_writer.h
@@ -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. + +#ifndef CC_PAINT_PAINT_OP_WRITER_H_ +#define CC_PAINT_PAINT_OP_WRITER_H_ + +#include "cc/paint/paint_canvas.h" + +struct SkRect; +struct SkIRect; +class SkRRect; + +namespace cc { + +class ImageDecodeCache; + +class PaintOpWriter { + public: + PaintOpWriter(void* memory, size_t size) + : memory_(static_cast<char*>(memory) + HeaderBytes()), + size_(size), + remaining_bytes_(size - HeaderBytes()) { + // Leave space for header of type/skip. + DCHECK_GE(size, HeaderBytes()); + } + + static size_t constexpr HeaderBytes() { return 4u; } + + // Write a sequence of arbitrary bytes. + void WriteData(size_t bytes, const void* input); + + void WriteArray(size_t count, const SkPoint* input); + + size_t size() const { return valid_ ? size_ - remaining_bytes_ : 0u; } + + void Write(SkScalar data); + void Write(size_t data); + void Write(uint8_t data); + void Write(const SkRect& rect); + void Write(const SkIRect& rect); + void Write(const SkRRect& rect); + + void Write(const SkPath& path); + void Write(const PaintFlags& flags); + void Write(const PaintImage& image, ImageDecodeCache* cache); + void Write(const sk_sp<SkData>& data); + void Write(const sk_sp<SkTextBlob>& blob); + + void Write(SkClipOp op) { Write(static_cast<uint8_t>(op)); } + void Write(PaintCanvas::AnnotationType type) { + Write(static_cast<uint8_t>(type)); + } + void Write(PaintCanvas::SrcRectConstraint constraint) { + Write(static_cast<uint8_t>(constraint)); + } + void Write(bool data) { Write(static_cast<uint8_t>(data)); } + + private: + template <typename T> + void WriteSimple(const T& val); + + char* memory_ = nullptr; + size_t size_ = 0u; + size_t remaining_bytes_ = 0u; + bool valid_ = true; +}; + +} // namespace cc + +#endif // CC_PAINT_PAINT_OP_WRITER_H_
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java index 29c0e760..1c5bce9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java
@@ -14,7 +14,6 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.test.ChromeActivityTestRule; @@ -36,7 +35,6 @@ */ @Test @MediumTest - @FlakyTest(message = "crbug.com/738148") public void testPoseDataUnfocusedTab() throws InterruptedException { mVrTestRule.loadUrlAndAwaitInitialization( VrTestRule.getHtmlTestFile("test_pose_data_unfocused_tab"), PAGE_LOAD_TIMEOUT_S);
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc index e16338c..76c3cf59 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -7,13 +7,17 @@ #include <memory> #include <utility> +#include "base/files/file_path.h" #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" +#include "base/sequenced_task_runner.h" +#include "base/task_scheduler/post_task.h" #include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h" #include "chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/channel_info.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_content_client.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h" @@ -21,6 +25,7 @@ #include "components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h" #include "components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.h" #include "components/offline_pages/core/prefetch/prefetch_service_impl.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" #include "content/public/browser/browser_context.h" @@ -49,15 +54,27 @@ content::BrowserContext* context) const { Profile* profile = Profile::FromBrowserContext(context); DCHECK(profile); + + auto offline_metrics_collector = + base::MakeUnique<OfflineMetricsCollectorImpl>(profile->GetPrefs()); + auto prefetch_dispatcher = base::MakeUnique<PrefetchDispatcherImpl>(); + auto prefetch_gcm_app_handler = base::MakeUnique<PrefetchGCMAppHandler>( base::MakeUnique<PrefetchInstanceIDProxy>(kPrefetchingOfflinePagesAppId, context)); + auto prefetch_network_request_factory = base::MakeUnique<PrefetchNetworkRequestFactoryImpl>( profile->GetRequestContext(), chrome::GetChannel(), GetUserAgent()); - auto offline_metrics_collector = - base::MakeUnique<OfflineMetricsCollectorImpl>(profile->GetPrefs()); + + scoped_refptr<base::SequencedTaskRunner> background_task_runner = + base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}); + base::FilePath store_path = + profile->GetPath().Append(chrome::kOfflinePagePrefetchStoreDirname); + auto prefetch_store = + base::MakeUnique<PrefetchStore>(background_task_runner, store_path); + auto suggested_articles_observer = base::MakeUnique<SuggestedArticlesObserver>(); @@ -68,7 +85,7 @@ return new PrefetchServiceImpl( std::move(offline_metrics_collector), std::move(prefetch_dispatcher), std::move(prefetch_gcm_app_handler), - std::move(prefetch_network_request_factory), + std::move(prefetch_network_request_factory), std::move(prefetch_store), std::move(suggested_articles_observer), std::move(prefetch_downloader)); }
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 2a3cda54b..7b796c30 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -776,168 +776,6 @@ } #endif -IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkCtrlLeftClick) { - GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf")); - WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); - ASSERT_TRUE(guest_contents); - - // The link position of the test-link.pdf in page coordinates is (110, 110). - // Convert the link position from page coordinates to screen coordinates. - gfx::Point link_position(110, 110); - ConvertPageCoordToScreenCoord(guest_contents, &link_position); - - WebContents* web_contents = GetActiveWebContents(); - - content::WindowedNotificationObserver observer( - chrome::NOTIFICATION_TAB_ADDED, - content::NotificationService::AllSources()); - content::SimulateMouseClickAt(web_contents, kDefaultKeyModifier, - blink::WebMouseEvent::Button::kLeft, - link_position); - observer.Wait(); - - int tab_count = browser()->tab_strip_model()->count(); - ASSERT_EQ(2, tab_count); - - WebContents* active_web_contents = GetActiveWebContents(); - ASSERT_EQ(web_contents, active_web_contents); - - WebContents* new_web_contents = - browser()->tab_strip_model()->GetWebContentsAt(1); - ASSERT_TRUE(new_web_contents); - ASSERT_NE(web_contents, new_web_contents); - - const GURL& url = new_web_contents->GetURL(); - ASSERT_EQ(std::string("http://www.example.com/"), url.spec()); -} - -IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkMiddleClick) { - GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf")); - WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); - ASSERT_TRUE(guest_contents); - - // The link position of the test-link.pdf in page coordinates is (110, 110). - // Convert the link position from page coordinates to screen coordinates. - gfx::Point link_position(110, 110); - ConvertPageCoordToScreenCoord(guest_contents, &link_position); - - WebContents* web_contents = GetActiveWebContents(); - - content::WindowedNotificationObserver observer( - chrome::NOTIFICATION_TAB_ADDED, - content::NotificationService::AllSources()); - content::SimulateMouseClickAt( - web_contents, 0, blink::WebMouseEvent::Button::kMiddle, link_position); - observer.Wait(); - - int tab_count = browser()->tab_strip_model()->count(); - ASSERT_EQ(2, tab_count); - - WebContents* active_web_contents = GetActiveWebContents(); - ASSERT_EQ(web_contents, active_web_contents); - - WebContents* new_web_contents = - browser()->tab_strip_model()->GetWebContentsAt(1); - ASSERT_TRUE(new_web_contents); - ASSERT_NE(web_contents, new_web_contents); - - const GURL& url = new_web_contents->GetURL(); - ASSERT_EQ(std::string("http://www.example.com/"), url.spec()); -} - -IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkCtrlShiftLeftClick) { - GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf")); - WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); - ASSERT_TRUE(guest_contents); - - // The link position of the test-link.pdf in page coordinates is (110, 110). - // Convert the link position from page coordinates to screen coordinates. - gfx::Point link_position(110, 110); - ConvertPageCoordToScreenCoord(guest_contents, &link_position); - - WebContents* web_contents = GetActiveWebContents(); - - int modifiers = blink::WebInputEvent::kShiftKey | kDefaultKeyModifier; - - content::WindowedNotificationObserver observer( - chrome::NOTIFICATION_TAB_ADDED, - content::NotificationService::AllSources()); - content::SimulateMouseClickAt(web_contents, modifiers, - blink::WebMouseEvent::Button::kLeft, - link_position); - observer.Wait(); - - int tab_count = browser()->tab_strip_model()->count(); - ASSERT_EQ(2, tab_count); - - WebContents* active_web_contents = GetActiveWebContents(); - ASSERT_NE(web_contents, active_web_contents); - - const GURL& url = active_web_contents->GetURL(); - ASSERT_EQ(std::string("http://www.example.com/"), url.spec()); -} - -IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkShiftMiddleClick) { - GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf")); - WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); - ASSERT_TRUE(guest_contents); - - // The link position of the test-link.pdf in page coordinates is (110, 110). - // Convert the link position from page coordinates to screen coordinates. - gfx::Point link_position(110, 110); - ConvertPageCoordToScreenCoord(guest_contents, &link_position); - - WebContents* web_contents = GetActiveWebContents(); - - content::WindowedNotificationObserver observer( - chrome::NOTIFICATION_TAB_ADDED, - content::NotificationService::AllSources()); - content::SimulateMouseClickAt(web_contents, blink::WebInputEvent::kShiftKey, - blink::WebMouseEvent::Button::kMiddle, - link_position); - observer.Wait(); - - int tab_count = browser()->tab_strip_model()->count(); - ASSERT_EQ(2, tab_count); - - WebContents* active_web_contents = GetActiveWebContents(); - ASSERT_NE(web_contents, active_web_contents); - - const GURL& url = active_web_contents->GetURL(); - ASSERT_EQ(std::string("http://www.example.com/"), url.spec()); -} - -IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkShiftLeftClick) { - GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf")); - WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); - ASSERT_TRUE(guest_contents); - ASSERT_EQ(1U, chrome::GetTotalBrowserCount()); - - // The link position of the test-link.pdf in page coordinates is (110, 110). - // Convert the link position from page coordinates to screen coordinates. - gfx::Point link_position(110, 110); - ConvertPageCoordToScreenCoord(guest_contents, &link_position); - - WebContents* web_contents = GetActiveWebContents(); - - content::WindowedNotificationObserver observer( - chrome::NOTIFICATION_BROWSER_WINDOW_READY, - content::NotificationService::AllSources()); - content::SimulateMouseClickAt(web_contents, blink::WebInputEvent::kShiftKey, - blink::WebMouseEvent::Button::kLeft, - link_position); - observer.Wait(); - - ASSERT_EQ(2U, chrome::GetTotalBrowserCount()); - - WebContents* active_web_contents = - chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); - ASSERT_NE(web_contents, active_web_contents); - - const GURL& url = active_web_contents->GetURL(); - ASSERT_EQ(std::string("http://www.example.com/"), url.spec()); -} - // Test that if the plugin tries to load a URL that redirects then it will fail // to load. This is to avoid the source origin of the document changing during // the redirect, which can have security implications. https://crbug.com/653749. @@ -954,8 +792,7 @@ WebContents* web_contents = GetActiveWebContents(); ui_test_utils::NavigateToURLWithDisposition( - browser(), GURL("about:blank"), - WindowOpenDisposition::NEW_FOREGROUND_TAB, + browser(), GURL("about:blank"), WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB | ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); WebContents* active_web_contents = GetActiveWebContents(); @@ -970,11 +807,187 @@ EXPECT_FALSE(active_web_contents->GetController().GetPendingEntry()); } +IN_PROC_BROWSER_TEST_F(PDFExtensionTest, OpenFromFTP) { + net::SpawnedTestServer ftp_server( + net::SpawnedTestServer::TYPE_FTP, net::SpawnedTestServer::kLocalhost, + base::FilePath(FILE_PATH_LITERAL("chrome/test/data/pdf"))); + ASSERT_TRUE(ftp_server.Start()); + + GURL url(ftp_server.GetURL("/test.pdf")); + ASSERT_TRUE(LoadPdf(url)); + EXPECT_EQ(base::ASCIIToUTF16("test.pdf"), GetActiveWebContents()->GetTitle()); +} + +class PDFExtensionLinkClickTest : public PDFExtensionTest { + public: + PDFExtensionLinkClickTest() : guest_contents_(nullptr) {} + ~PDFExtensionLinkClickTest() override {} + + protected: + void LoadTestLinkPdfGetGuestContents() { + GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf")); + guest_contents_ = LoadPdfGetGuestContents(test_pdf_url); + ASSERT_TRUE(guest_contents_); + } + + // The rectangle of the link in test-link.pdf is [72 706 164 719] in PDF user + // space. To calculate a position inside this rectangle, several + // transformations have to be applied: + // [a] (110, 110) in Blink page coordinates -> + // [b] (219, 169) in Blink screen coordinates -> + // [c] (115, 169) in PDF Device space coordinates -> + // [d] (82.5, 709.5) in PDF user space coordinates. + // This performs the [a] to [b] transformation, since that is the coordinate + // space content::SimulateMouseClickAt() needs. + gfx::Point GetLinkPosition() { + gfx::Point link_position(110, 110); + ConvertPageCoordToScreenCoord(guest_contents_, &link_position); + return link_position; + } + + void SetGuestContents(WebContents* guest_contents) { + ASSERT_TRUE(guest_contents); + guest_contents_ = guest_contents; + } + + private: + WebContents* guest_contents_; +}; + +IN_PROC_BROWSER_TEST_F(PDFExtensionLinkClickTest, CtrlLeft) { + LoadTestLinkPdfGetGuestContents(); + + WebContents* web_contents = GetActiveWebContents(); + + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_TAB_ADDED, + content::NotificationService::AllSources()); + content::SimulateMouseClickAt(web_contents, kDefaultKeyModifier, + blink::WebMouseEvent::Button::kLeft, + GetLinkPosition()); + observer.Wait(); + + int tab_count = browser()->tab_strip_model()->count(); + ASSERT_EQ(2, tab_count); + + WebContents* active_web_contents = GetActiveWebContents(); + ASSERT_EQ(web_contents, active_web_contents); + + WebContents* new_web_contents = + browser()->tab_strip_model()->GetWebContentsAt(1); + ASSERT_TRUE(new_web_contents); + ASSERT_NE(web_contents, new_web_contents); + + const GURL& url = new_web_contents->GetURL(); + EXPECT_EQ("http://www.example.com/", url.spec()); +} + +IN_PROC_BROWSER_TEST_F(PDFExtensionLinkClickTest, Middle) { + LoadTestLinkPdfGetGuestContents(); + + WebContents* web_contents = GetActiveWebContents(); + + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_TAB_ADDED, + content::NotificationService::AllSources()); + content::SimulateMouseClickAt(web_contents, 0, + blink::WebMouseEvent::Button::kMiddle, + GetLinkPosition()); + observer.Wait(); + + int tab_count = browser()->tab_strip_model()->count(); + ASSERT_EQ(2, tab_count); + + WebContents* active_web_contents = GetActiveWebContents(); + ASSERT_EQ(web_contents, active_web_contents); + + WebContents* new_web_contents = + browser()->tab_strip_model()->GetWebContentsAt(1); + ASSERT_TRUE(new_web_contents); + ASSERT_NE(web_contents, new_web_contents); + + const GURL& url = new_web_contents->GetURL(); + EXPECT_EQ("http://www.example.com/", url.spec()); +} + +IN_PROC_BROWSER_TEST_F(PDFExtensionLinkClickTest, CtrlShiftLeft) { + LoadTestLinkPdfGetGuestContents(); + + WebContents* web_contents = GetActiveWebContents(); + + const int modifiers = blink::WebInputEvent::kShiftKey | kDefaultKeyModifier; + + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_TAB_ADDED, + content::NotificationService::AllSources()); + content::SimulateMouseClickAt(web_contents, modifiers, + blink::WebMouseEvent::Button::kLeft, + GetLinkPosition()); + observer.Wait(); + + int tab_count = browser()->tab_strip_model()->count(); + ASSERT_EQ(2, tab_count); + + WebContents* active_web_contents = GetActiveWebContents(); + ASSERT_NE(web_contents, active_web_contents); + + const GURL& url = active_web_contents->GetURL(); + EXPECT_EQ("http://www.example.com/", url.spec()); +} + +IN_PROC_BROWSER_TEST_F(PDFExtensionLinkClickTest, ShiftMiddle) { + LoadTestLinkPdfGetGuestContents(); + + WebContents* web_contents = GetActiveWebContents(); + + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_TAB_ADDED, + content::NotificationService::AllSources()); + content::SimulateMouseClickAt(web_contents, blink::WebInputEvent::kShiftKey, + blink::WebMouseEvent::Button::kMiddle, + GetLinkPosition()); + observer.Wait(); + + int tab_count = browser()->tab_strip_model()->count(); + ASSERT_EQ(2, tab_count); + + WebContents* active_web_contents = GetActiveWebContents(); + ASSERT_NE(web_contents, active_web_contents); + + const GURL& url = active_web_contents->GetURL(); + EXPECT_EQ("http://www.example.com/", url.spec()); +} + +IN_PROC_BROWSER_TEST_F(PDFExtensionLinkClickTest, ShiftLeft) { + LoadTestLinkPdfGetGuestContents(); + + ASSERT_EQ(1U, chrome::GetTotalBrowserCount()); + + WebContents* web_contents = GetActiveWebContents(); + + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_BROWSER_WINDOW_READY, + content::NotificationService::AllSources()); + content::SimulateMouseClickAt(web_contents, blink::WebInputEvent::kShiftKey, + blink::WebMouseEvent::Button::kLeft, + GetLinkPosition()); + observer.Wait(); + + ASSERT_EQ(2U, chrome::GetTotalBrowserCount()); + + WebContents* active_web_contents = + chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); + ASSERT_NE(web_contents, active_web_contents); + + const GURL& url = active_web_contents->GetURL(); + EXPECT_EQ("http://www.example.com/", url.spec()); +} + // This test opens a PDF by clicking a link via javascript and verifies that // the PDF is loaded and functional by clicking a link in the PDF. The link // click in the PDF opens a new tab. The main page handles the pageShow event // and updates the history state. -IN_PROC_BROWSER_TEST_F(PDFExtensionTest, OpenPDFOnLinkClickWithReplaceState) { +IN_PROC_BROWSER_TEST_F(PDFExtensionLinkClickTest, OpenPDFWithReplaceState) { // Navigate to the main page. GURL test_url( embedded_test_server()->GetURL("/pdf/pdf_href_replace_state.html")); @@ -997,19 +1010,14 @@ // tab. content::BrowserPluginGuestManager* guest_manager = web_contents->GetBrowserContext()->GetGuestManager(); - WebContents* guest_contents = guest_manager->GetFullPageGuest(web_contents); - ASSERT_TRUE(guest_contents); - // The link position of the test-link.pdf in page coordinates is (110, 110). - // Convert the link position from page coordinates to screen coordinates. - gfx::Point link_position(110, 110); - ConvertPageCoordToScreenCoord(guest_contents, &link_position); + SetGuestContents(guest_manager->GetFullPageGuest(web_contents)); content::WindowedNotificationObserver observer( chrome::NOTIFICATION_TAB_ADDED, content::NotificationService::AllSources()); content::SimulateMouseClickAt(web_contents, kDefaultKeyModifier, blink::WebMouseEvent::Button::kLeft, - link_position); + GetLinkPosition()); observer.Wait(); // We should have two tabs now. One with the PDF and the second for @@ -1026,16 +1034,5 @@ ASSERT_NE(web_contents, new_web_contents); const GURL& url = new_web_contents->GetURL(); - ASSERT_EQ(GURL("http://www.example.com"), url); -} - -IN_PROC_BROWSER_TEST_F(PDFExtensionTest, OpenFromFTP) { - net::SpawnedTestServer ftp_server( - net::SpawnedTestServer::TYPE_FTP, net::SpawnedTestServer::kLocalhost, - base::FilePath(FILE_PATH_LITERAL("chrome/test/data/pdf"))); - ASSERT_TRUE(ftp_server.Start()); - - GURL url(ftp_server.GetURL("/test.pdf")); - ASSERT_TRUE(LoadPdf(url)); - EXPECT_EQ(base::ASCIIToUTF16("test.pdf"), GetActiveWebContents()->GetTitle()); + EXPECT_EQ("http://www.example.com/", url.spec()); }
diff --git a/chrome/browser/resources/md_extensions/animation_helper.js b/chrome/browser/resources/md_extensions/animation_helper.js index a429f184..00483b37 100644 --- a/chrome/browser/resources/md_extensions/animation_helper.js +++ b/chrome/browser/resources/md_extensions/animation_helper.js
@@ -22,24 +22,25 @@ * A helper object for setting entry/exit animations. Polymer's support of * this is pretty limited, since it doesn't allow for things like specifying * hero properties or nodes. - * @param {!HTMLElement} element The parent element to set the animations on. - * This will be used as the page in to/fromPage. - * @param {?HTMLElement} node The node to use for scaling and fading - * animations. - * @constructor */ - function AnimationHelper(element, node) { - this.element_ = element; - this.node_ = node; - element.animationConfig = {}; - } + class AnimationHelper { + /** + * @param {!HTMLElement} element The parent element to set the animations + * on. This will be used as the page in to/fromPage. + * @param {?HTMLElement} node The node to use for scaling and fading + * animations. + */ + constructor(element, node) { + this.element_ = element; + this.node_ = node; + element.animationConfig = {}; + } - AnimationHelper.prototype = { /** * Set the entry animation for the element. * @param {!Array<extensions.Animation>} animations */ - setEntryAnimations: function(animations) { + setEntryAnimations(animations) { var configs = []; for (let animation of animations) { switch (animation) { @@ -56,13 +57,13 @@ } } this.element_.animationConfig.entry = configs; - }, + } /** * Set the exit animation for the element. * @param {!Array<extensions.Animation>} animations */ - setExitAnimations: function(animations) { + setExitAnimations(animations) { var configs = []; for (let animation of animations) { switch (animation) { @@ -88,8 +89,8 @@ } } this.element_.animationConfig.exit = configs; - }, - }; + } + } return {AnimationHelper: AnimationHelper}; });
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js index f4070d3..4bac6d8 100644 --- a/chrome/browser/resources/md_extensions/manager.js +++ b/chrome/browser/resources/md_extensions/manager.js
@@ -422,18 +422,15 @@ } }); - /** - * @param {extensions.Manager} manager - * @constructor - * @implements {extensions.SidebarListDelegate} - */ - function ListHelper(manager) { - this.manager_ = manager; - } + /** @implements {extensions.SidebarListDelegate} */ + class ListHelper { + /** @param {extensions.Manager} manager */ + constructor(manager) { + this.manager_ = manager; + } - ListHelper.prototype = { /** @override */ - showType: function(type) { + showType(type) { var items; switch (type) { case extensions.ShowingType.EXTENSIONS: @@ -446,13 +443,13 @@ this.manager_.$ /* hack */['items-list'].set('items', assert(items)); this.manager_.changePage({page: Page.LIST}); - }, + } /** @override */ - showKeyboardShortcuts: function() { + showKeyboardShortcuts() { this.manager_.changePage({page: Page.SHORTCUTS}); - }, - }; + } + } return {Manager: Manager}; });
diff --git a/chrome/browser/resources/md_extensions/navigation_helper.js b/chrome/browser/resources/md_extensions/navigation_helper.js index 43e2382..d15ca5996 100644 --- a/chrome/browser/resources/md_extensions/navigation_helper.js +++ b/chrome/browser/resources/md_extensions/navigation_helper.js
@@ -31,26 +31,28 @@ * A helper object to manage in-page navigations. Since the extensions page * needs to support different urls for different subpages (like the details * page), we use this object to manage the history and url conversions. - * @param {!function(!PageState):void} onHistoryChange A function to call when - * the page has changed as a result of the user going back or forward in - * history; called with the new active page. - * @constructor */ - function NavigationHelper(onHistoryChange) { - this.onHistoryChange_ = onHistoryChange; - window.addEventListener('popstate', this.onPopState_.bind(this)); - } + */ + class NavigationHelper { + /** + * @param {!function(!PageState):void} onHistoryChange A function to call + * when the page has changed as a result of the user going back or + * forward in history; called with the new active page. + */ + constructor(onHistoryChange) { + this.onHistoryChange_ = onHistoryChange; + window.addEventListener('popstate', this.onPopState_.bind(this)); + } - NavigationHelper.prototype = { /** @private */ - onPopState_: function() { + onPopState_() { this.onHistoryChange_(this.getCurrentPage()); - }, + } /** - * Returns the page that should be displayed for the current URL. - * @return {!PageState} + * @return {!PageState} The page that should be displayed for the current + * URL. */ - getCurrentPage: function() { + getCurrentPage() { var search = new URLSearchParams(location.search); var id = search.get('id'); if (id) @@ -66,13 +68,13 @@ return {page: Page.SHORTCUTS}; return {page: Page.LIST}; - }, + } /** * Called when a page changes, and pushes state to history to reflect it. * @param {!PageState} entry */ - updateHistory: function(entry) { + updateHistory(entry) { var path; switch (entry.page) { case Page.LIST: @@ -106,8 +108,8 @@ history.replaceState(state, '', path); else history.pushState(state, '', path); - }, - }; + } + } return {NavigationHelper: NavigationHelper}; });
diff --git a/chrome/browser/resources/md_extensions/service.js b/chrome/browser/resources/md_extensions/service.js index c65380f..9694a3a 100644 --- a/chrome/browser/resources/md_extensions/service.js +++ b/chrome/browser/resources/md_extensions/service.js
@@ -6,22 +6,26 @@ 'use strict'; /** - * @constructor * @implements {extensions.ErrorPageDelegate} * @implements {extensions.ItemDelegate} * @implements {extensions.LoadErrorDelegate} * @implements {extensions.PackDialogDelegate} * @implements {extensions.ToolbarDelegate} */ - function Service() {} + class Service { + constructor() { + /** @private {boolean} */ + this.isDeleting_ = false; - Service.prototype = { - /** @private {boolean} */ - isDeleting_: false, + /** @private {extensions.Manager} */ + this.manager_; + + /** @private {Array<chrome.developerPrivate.ExtensionInfo>} */ + this.extensions_; + } /** @param {extensions.Manager} manager */ - managerReady: function(manager) { - /** @private {extensions.Manager} */ + managerReady(manager) { this.manager_ = manager; this.manager_.toolbar.setDelegate(this); this.manager_.set('itemDelegate', this); @@ -44,7 +48,6 @@ chrome.developerPrivate.getExtensionsInfo( {includeDisabled: true, includeTerminated: true}, function(extensions) { - /** @private {Array<chrome.developerPrivate.ExtensionInfo>} */ this.extensions_ = extensions; for (let extension of extensions) this.manager_.addItem(extension); @@ -53,21 +56,21 @@ }.bind(this)); chrome.developerPrivate.getProfileConfiguration( this.onProfileStateChanged_.bind(this)); - }, + } /** * @param {chrome.developerPrivate.ProfileInfo} profileInfo * @private */ - onProfileStateChanged_: function(profileInfo) { + onProfileStateChanged_(profileInfo) { this.manager_.set('inDevMode', profileInfo.inDeveloperMode); - }, + } /** * @param {chrome.developerPrivate.EventData} eventData * @private */ - onItemStateChanged_: function(eventData) { + onItemStateChanged_(eventData) { var currentIndex = this.extensions_.findIndex(function(extension) { return extension.id == eventData.item_id; }); @@ -103,7 +106,7 @@ default: assertNotReached(); } - }, + } /** * Opens a file browser dialog for the user to select a file (or directory). @@ -112,7 +115,7 @@ * @return {Promise<string>} The promise to be resolved with the selected * path. */ - chooseFilePath_: function(selectType, fileType) { + chooseFilePath_(selectType, fileType) { return new Promise(function(resolve, reject) { chrome.developerPrivate.choosePath( selectType, fileType, function(path) { @@ -124,20 +127,20 @@ } }); }); - }, + } /** * Updates an extension command. * @param {!CustomEvent} e * @private */ - onExtensionCommandUpdated_: function(e) { + onExtensionCommandUpdated_(e) { chrome.developerPrivate.updateExtensionCommand({ extensionId: e.detail.item, commandName: e.detail.commandName, keybinding: e.detail.keybinding, }); - }, + } /** * Called when shortcut capturing changes in order to suspend or re-enable @@ -150,9 +153,9 @@ * @param {!CustomEvent} e * @private */ - onShortcutCaptureChanged_: function(isCapturing, e) { + onShortcutCaptureChanged_(isCapturing, e) { chrome.developerPrivate.setShortcutHandlingSuspended(isCapturing); - }, + } /** * Attempts to load an unpacked extension, optionally as another attempt at @@ -160,7 +163,7 @@ * @param {string=} opt_retryGuid * @private */ - loadUnpackedHelper_: function(opt_retryGuid) { + loadUnpackedHelper_(opt_retryGuid) { chrome.developerPrivate.loadUnpacked( {failQuietly: true, populateError: true, retryGuid: opt_retryGuid}, (loadError) => { @@ -174,10 +177,10 @@ this.manager_.loadError.show(); } }); - }, + } /** @override */ - deleteItem: function(id) { + deleteItem(id) { if (this.isDeleting_) return; this.isDeleting_ = true; @@ -188,67 +191,67 @@ chrome.runtime.lastError; this.isDeleting_ = false; }.bind(this)); - }, + } /** @override */ - setItemEnabled: function(id, isEnabled) { + setItemEnabled(id, isEnabled) { chrome.management.setEnabled(id, isEnabled); - }, + } /** @override */ - setItemAllowedIncognito: function(id, isAllowedIncognito) { + setItemAllowedIncognito(id, isAllowedIncognito) { chrome.developerPrivate.updateExtensionConfiguration({ extensionId: id, incognitoAccess: isAllowedIncognito, }); - }, + } /** @override */ - setItemAllowedOnFileUrls: function(id, isAllowedOnFileUrls) { + setItemAllowedOnFileUrls(id, isAllowedOnFileUrls) { chrome.developerPrivate.updateExtensionConfiguration({ extensionId: id, fileAccess: isAllowedOnFileUrls, }); - }, + } /** @override */ - setItemAllowedOnAllSites: function(id, isAllowedOnAllSites) { + setItemAllowedOnAllSites(id, isAllowedOnAllSites) { chrome.developerPrivate.updateExtensionConfiguration({ extensionId: id, runOnAllUrls: isAllowedOnAllSites, }); - }, + } /** @override */ - setItemCollectsErrors: function(id, collectsErrors) { + setItemCollectsErrors(id, collectsErrors) { chrome.developerPrivate.updateExtensionConfiguration({ extensionId: id, errorCollection: collectsErrors, }); - }, + } /** @override */ - inspectItemView: function(id, view) { + inspectItemView(id, view) { chrome.developerPrivate.openDevTools({ extensionId: id, renderProcessId: view.renderProcessId, renderViewId: view.renderViewId, incognito: view.incognito, }); - }, + } /** @override */ - reloadItem: function(id) { + reloadItem(id) { chrome.developerPrivate.reload(id, {failQuietly: false}); - }, + } /** @override */ - repairItem: function(id) { + repairItem(id) { chrome.developerPrivate.repairExtension(id); - }, + } /** @override */ - showItemOptionsPage: function(id) { + showItemOptionsPage(id) { var extension = this.extensions_.find(function(e) { return e.id == id; }); @@ -259,66 +262,66 @@ this.manager_.changePage( {page: Page.DETAILS, subpage: Dialog.OPTIONS, extensionId: id}); } - }, + } /** @override */ - setProfileInDevMode: function(inDevMode) { + setProfileInDevMode(inDevMode) { chrome.developerPrivate.updateProfileConfiguration( {inDeveloperMode: inDevMode}); - }, + } /** @override */ - loadUnpacked: function() { + loadUnpacked() { this.loadUnpackedHelper_(); - }, + } /** @override */ - retryLoadUnpacked: function(retryGuid) { + retryLoadUnpacked(retryGuid) { this.loadUnpackedHelper_(retryGuid); - }, + } /** @override */ - choosePackRootDirectory: function() { + choosePackRootDirectory() { return this.chooseFilePath_( chrome.developerPrivate.SelectType.FOLDER, chrome.developerPrivate.FileType.LOAD); - }, + } /** @override */ - choosePrivateKeyPath: function() { + choosePrivateKeyPath() { return this.chooseFilePath_( chrome.developerPrivate.SelectType.FILE, chrome.developerPrivate.FileType.PEM); - }, + } /** @override */ - packExtension: function(rootPath, keyPath) { + packExtension(rootPath, keyPath) { chrome.developerPrivate.packDirectory(rootPath, keyPath); - }, + } /** @override */ - updateAllExtensions: function() { + updateAllExtensions() { chrome.developerPrivate.autoUpdate(); - }, + } /** @override */ - deleteErrors: function(extensionId, errorIds, type) { + deleteErrors(extensionId, errorIds, type) { chrome.developerPrivate.deleteExtensionErrors({ extensionId: extensionId, errorIds: errorIds, type: type, }); - }, + } /** @override */ - requestFileSource: function(args) { + requestFileSource(args) { return new Promise(function(resolve, reject) { chrome.developerPrivate.requestFileSource(args, function(code) { resolve(code); }); }); - }, - }; + } + } cr.addSingletonGetter(Service);
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index aae349ce..d4c4c64 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -8,6 +8,7 @@ #include <vector> +#include "ash/public/interfaces/constants.mojom.h" #include "base/command_line.h" #include "base/metrics/user_metrics.h" #include "base/profiler/scoped_tracker.h" @@ -38,11 +39,13 @@ #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/speech_recognition_session_preamble.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/service_manager_connection.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" #include "extensions/common/extension_set.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/launcher_page_info.h" +#include "services/service_manager/public/cpp/connector.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/search_box_model.h" #include "ui/app_list/search_controller.h" @@ -105,9 +108,11 @@ AppListViewDelegate::AppListViewDelegate(AppListControllerDelegate* controller) : controller_(controller), - profile_(NULL), - model_(NULL), - template_url_service_observer_(this) { + profile_(nullptr), + model_(nullptr), + template_url_service_observer_(this), + observer_binding_(this), + weak_ptr_factory_(this) { CHECK(controller_); speech_ui_.reset(new app_list::SpeechUIModel); @@ -127,6 +132,13 @@ registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, content::NotificationService::AllSources()); + + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &wallpaper_controller_ptr_); + ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + wallpaper_controller_ptr_->AddObserver(std::move(ptr_info)); } AppListViewDelegate::~AppListViewDelegate() { @@ -183,6 +195,12 @@ model_ = app_list::AppListSyncableServiceFactory::GetForProfile(profile_) ->GetModel(); + // After |model_| is initialized, make a GetWallpaperColors mojo call to set + // wallpaper colors for |model_|. + wallpaper_controller_ptr_->GetWallpaperColors( + base::Bind(&AppListViewDelegate::OnGetWallpaperColorsCallback, + weak_ptr_factory_.GetWeakPtr())); + app_sync_ui_state_watcher_.reset( new AppSyncUIStateWatcher(profile_, model_)); @@ -195,6 +213,11 @@ model_->search_box()->Update(base::string16(), false); } +void AppListViewDelegate::OnGetWallpaperColorsCallback( + const std::vector<SkColor>& colors) { + OnWallpaperColorsChanged(colors); +} + void AppListViewDelegate::SetUpSearchUI() { app_list::StartPageService* start_page_service = app_list::StartPageService::Get(profile_); @@ -241,6 +264,14 @@ first_launcher_page_app_id)); } +void AppListViewDelegate::OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) { + if (!model_) + return; + + model_->search_box()->SetWallpaperProminentColors(prominent_colors); +} + void AppListViewDelegate::OnHotwordStateChanged(bool started) { if (started) { if (speech_ui_->state() == app_list::SPEECH_RECOGNITION_READY) {
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h index 0a5d7540..67e59f1 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.h +++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -11,9 +11,11 @@ #include <string> #include <vector> +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "chrome/browser/search/hotword_client.h" #include "chrome/browser/ui/app_list/start_page_observer.h" @@ -21,6 +23,8 @@ #include "components/search_engines/template_url_service_observer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "mojo/public/cpp/bindings/associated_binding.h" +#include "mojo/public/cpp/bindings/binding.h" #include "ui/app_list/app_list_view_delegate.h" namespace app_list { @@ -41,6 +45,7 @@ class AppListViewDelegate : public app_list::AppListViewDelegate, public app_list::StartPageObserver, + public ash::mojom::WallpaperObserver, public HotwordClient, public content::NotificationObserver, public TemplateURLServiceObserver { @@ -87,6 +92,9 @@ void OnTemplateURLServiceChanged() override; private: + // Callback for ash::mojom::GetWallpaperColors. + void OnGetWallpaperColorsCallback(const std::vector<SkColor>& colors); + // Updates the speech webview and start page for the current |profile_|. void SetUpSearchUI(); @@ -99,6 +107,10 @@ void OnSpeechRecognitionStateChanged( app_list::SpeechRecognitionState new_state) override; + // Overridden from ash::mojom::WallpaperObserver: + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override; + // Overridden from HotwordClient: void OnHotwordStateChanged(bool started) override; void OnHotwordRecognized( @@ -142,6 +154,14 @@ // Registers for NOTIFICATION_APP_TERMINATING to unload custom launcher pages. content::NotificationRegistrar registrar_; + // The binding this instance uses to implement mojom::WallpaperObserver. + mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_; + + // Ash's mojom::WallpaperController. + ash::mojom::WallpaperControllerPtr wallpaper_controller_ptr_; + + base::WeakPtrFactory<AppListViewDelegate> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(AppListViewDelegate); };
diff --git a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc index b017fc6..ff960d9f 100644 --- a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc
@@ -188,4 +188,273 @@ JourneyLogger::NOT_SHOWN_REASON_CONCURRENT_REQUESTS, 1); } +class PaymentRequestJourneyLoggerAllSectionStatsTest + : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestJourneyLoggerAllSectionStatsTest() + : PaymentRequestBrowserTestBase( + "/payment_request_contact_details_and_free_shipping_test.html") {} + + private: + DISALLOW_COPY_AND_ASSIGN(PaymentRequestJourneyLoggerAllSectionStatsTest); +}; + +// Tests that the correct number of suggestions shown for each section is logged +// when a Payment Request is completed. +IN_PROC_BROWSER_TEST_F(PaymentRequestJourneyLoggerAllSectionStatsTest, + NumberOfSuggestionsShown_Completed) { + base::HistogramTester histogram_tester; + + // Setup a credit card with an associated billing address. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // Visa. + + // Add another address. + AddAutofillProfile(autofill::test::GetFullProfile2()); + + // Complete the Payment Request. + InvokePaymentRequestUI(); + ResetEventObserver(DialogEvent::DIALOG_CLOSED); + PayWithCreditCardAndWait(base::ASCIIToUTF16("123")); + + // Expect the appropriate number of suggestions shown to be logged. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.CreditCards.Completed", 1, 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ShippingAddress.Completed", 2, + 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ContactInfo.Completed", 2, 1); +} + +// Tests that the correct number of suggestions shown for each section is logged +// when a Payment Request is aborted by the user. +IN_PROC_BROWSER_TEST_F(PaymentRequestJourneyLoggerAllSectionStatsTest, + NumberOfSuggestionsShown_UserAborted) { + base::HistogramTester histogram_tester; + + // Setup a credit card with an associated billing address. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // Visa. + + // Add another address. + AddAutofillProfile(autofill::test::GetFullProfile2()); + + // The user aborts the Payment Request. + InvokePaymentRequestUI(); + ClickOnCancel(); + + // Expect the appropriate number of suggestions shown to be logged. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.CreditCards.UserAborted", 1, 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ShippingAddress.UserAborted", 2, + 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ContactInfo.UserAborted", 2, 1); +} + +class PaymentRequestJourneyLoggerNoShippingSectionStatsTest + : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestJourneyLoggerNoShippingSectionStatsTest() + : PaymentRequestBrowserTestBase( + "/payment_request_contact_details_test.html") {} + + private: + DISALLOW_COPY_AND_ASSIGN( + PaymentRequestJourneyLoggerNoShippingSectionStatsTest); +}; + +// Tests that the correct number of suggestions shown for each section is logged +// when a Payment Request is completed. +IN_PROC_BROWSER_TEST_F(PaymentRequestJourneyLoggerNoShippingSectionStatsTest, + NumberOfSuggestionsShown_Completed) { + base::HistogramTester histogram_tester; + + // Setup a credit card with an associated billing address. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // Visa. + + // Add another address. + AddAutofillProfile(autofill::test::GetFullProfile2()); + + // Complete the Payment Request. + InvokePaymentRequestUI(); + ResetEventObserver(DialogEvent::DIALOG_CLOSED); + PayWithCreditCardAndWait(base::ASCIIToUTF16("123")); + + // Expect the appropriate number of suggestions shown to be logged. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.CreditCards.Completed", 1, 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ContactInfo.Completed", 2, 1); + + // There should be no log for shipping address since it was not requested. + histogram_tester.ExpectTotalCount( + "PaymentRequest.NumberOfSuggestionsShown.ShippingAddress.Completed", 0); +} + +// Tests that the correct number of suggestions shown for each section is logged +// when a Payment Request is aborted by the user. +IN_PROC_BROWSER_TEST_F(PaymentRequestJourneyLoggerNoShippingSectionStatsTest, + NumberOfSuggestionsShown_UserAborted) { + base::HistogramTester histogram_tester; + + // Setup a credit card with an associated billing address. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // Visa. + + // Add another address. + AddAutofillProfile(autofill::test::GetFullProfile2()); + + // The user aborts the Payment Request. + InvokePaymentRequestUI(); + ClickOnCancel(); + + // Expect the appropriate number of suggestions shown to be logged. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.CreditCards.UserAborted", 1, 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ContactInfo.UserAborted", 2, 1); + + // There should be no log for shipping address since it was not requested. + histogram_tester.ExpectTotalCount( + "PaymentRequest.NumberOfSuggestionsShown.ShippingAddress.UserAborted", 0); +} + +class PaymentRequestJourneyLoggerNoContactDetailSectionStatsTest + : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestJourneyLoggerNoContactDetailSectionStatsTest() + : PaymentRequestBrowserTestBase( + "/payment_request_free_shipping_test.html") {} + + private: + DISALLOW_COPY_AND_ASSIGN( + PaymentRequestJourneyLoggerNoContactDetailSectionStatsTest); +}; + +// Tests that the correct number of suggestions shown for each section is logged +// when a Payment Request is completed. +IN_PROC_BROWSER_TEST_F( + PaymentRequestJourneyLoggerNoContactDetailSectionStatsTest, + NumberOfSuggestionsShown_Completed) { + base::HistogramTester histogram_tester; + + // Setup a credit card with an associated billing address. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // Visa. + + // Add another address. + AddAutofillProfile(autofill::test::GetFullProfile2()); + + // Complete the Payment Request. + InvokePaymentRequestUI(); + ResetEventObserver(DialogEvent::DIALOG_CLOSED); + PayWithCreditCardAndWait(base::ASCIIToUTF16("123")); + + // Expect the appropriate number of suggestions shown to be logged. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.CreditCards.Completed", 1, 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ShippingAddress.Completed", 2, + 1); + + // There should be no log for contact info since it was not requested. + histogram_tester.ExpectTotalCount( + "PaymentRequest.NumberOfSuggestionsShown.ContactInfo.Completed", 0); +} + +// Tests that the correct number of suggestions shown for each section is logged +// when a Payment Request is aborted by the user. +IN_PROC_BROWSER_TEST_F( + PaymentRequestJourneyLoggerNoContactDetailSectionStatsTest, + NumberOfSuggestionsShown_UserAborted) { + base::HistogramTester histogram_tester; + + // Setup a credit card with an associated billing address. + autofill::AutofillProfile billing_address = autofill::test::GetFullProfile(); + AddAutofillProfile(billing_address); + autofill::CreditCard card = autofill::test::GetCreditCard(); + card.set_billing_address_id(billing_address.guid()); + AddCreditCard(card); // Visa. + + // Add another address. + AddAutofillProfile(autofill::test::GetFullProfile2()); + + // The user aborts the Payment Request. + InvokePaymentRequestUI(); + ClickOnCancel(); + + // Expect the appropriate number of suggestions shown to be logged. + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.CreditCards.UserAborted", 1, 1); + histogram_tester.ExpectUniqueSample( + "PaymentRequest.NumberOfSuggestionsShown.ShippingAddress.UserAborted", 2, + 1); + + // There should be no log for contact info since it was not requested. + histogram_tester.ExpectTotalCount( + "PaymentRequest.NumberOfSuggestionsShown.ContactInfo.UserAborted", 0); +} + +class PaymentRequestNotShownTest : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestNotShownTest() + : PaymentRequestBrowserTestBase( + "/payment_request_can_make_payment_metrics_test.html") {} + + private: + DISALLOW_COPY_AND_ASSIGN(PaymentRequestNotShownTest); +}; + +IN_PROC_BROWSER_TEST_F(PaymentRequestNotShownTest, OnlyNotShownMetricsLogged) { + base::HistogramTester histogram_tester; + + // Initiate a Payment Request without showing it. + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "queryNoShow();")); + + // Navigate away to abort the Payment Request and trigger the logs. + NavigateTo("/payment_request_email_test.html"); + + // Initiated should be logged. + histogram_tester.ExpectBucketCount("PaymentRequest.CheckoutFunnel.Initiated", + 1, 1); + // Show should not be logged. + histogram_tester.ExpectTotalCount("PaymentRequest.CheckoutFunnel.Shown", 0); + // Abort should not be logged. + histogram_tester.ExpectTotalCount("PaymentRequest.CheckoutFunnel.Aborted", 0); + + // Make sure that the metrics that required the Payment Request to be shown + // are not logged. + histogram_tester.ExpectTotalCount("PaymentRequest.SelectedPaymentMethod", 0); + histogram_tester.ExpectTotalCount("PaymentRequest.RequestedInformation", 0); + histogram_tester.ExpectTotalCount("PaymentRequest.NumberOfSelectionAdds", 0); + histogram_tester.ExpectTotalCount("PaymentRequest.NumberOfSelectionChanges", + 0); + histogram_tester.ExpectTotalCount("PaymentRequest.NumberOfSelectionEdits", 0); + histogram_tester.ExpectTotalCount("PaymentRequest.NumberOfSuggestionsShown", + 0); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserHadSuggestionsForEverything", 0); + histogram_tester.ExpectTotalCount( + "PaymentRequest.UserDidNotHaveSuggestionsForEverything", 0); +} + } // namespace payments
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc index 7ebb5ea..0a22244 100644 --- a/chrome/browser/win/jumplist.cc +++ b/chrome/browser/win/jumplist.cc
@@ -309,6 +309,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (timer_.IsRunning()) { + // TODO(chengx): Remove the UMA histogram below after fixing crbug/733034. + UMA_HISTOGRAM_COUNTS_10000( + "WinJumplist.NotificationTimeInterval", + (timer_.desired_run_time() - base::TimeTicks::Now()).InMilliseconds()); timer_.Reset(); } else { // base::Unretained is safe since |this| is guaranteed to outlive timer_.
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index 94cdc2a..e4ce7d5 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc
@@ -157,6 +157,8 @@ FPL("Offline Pages/archives"); const base::FilePath::CharType kOfflinePageMetadataDirname[] = FPL("Offline Pages/metadata"); +const base::FilePath::CharType kOfflinePagePrefetchStoreDirname[] = + FPL("Offline Pages/prefech_store"); const base::FilePath::CharType kOfflinePageRequestQueueDirname[] = FPL("Offline Pages/request_queue"); const base::FilePath::CharType kPreferencesFilename[] = FPL("Preferences");
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 8321b76..a170109 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h
@@ -59,6 +59,7 @@ extern const base::FilePath::CharType kMediaCacheDirname[]; extern const base::FilePath::CharType kOfflinePageArchivesDirname[]; extern const base::FilePath::CharType kOfflinePageMetadataDirname[]; +extern const base::FilePath::CharType kOfflinePagePrefetchStoreDirname[]; extern const base::FilePath::CharType kOfflinePageRequestQueueDirname[]; extern const base::FilePath::CharType kPreferencesFilename[]; extern const base::FilePath::CharType kPreviewsOptOutDBFilename[];
diff --git a/chrome/test/data/payments/contact_details.js b/chrome/test/data/payments/contact_details.js index e4e4df9..67eca44 100644 --- a/chrome/test/data/payments/contact_details.js +++ b/chrome/test/data/payments/contact_details.js
@@ -12,7 +12,7 @@ function buy() { // eslint-disable-line no-unused-vars try { new PaymentRequest( - [{supportedMethods: ['https://bobpay.com', 'amex']}], + [{supportedMethods: ['https://bobpay.com', 'amex', 'visa']}], {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}}, {requestPayerName: true, requestPayerEmail: true, requestPayerPhone: true})
diff --git a/chromeos/components/tether/BUILD.gn b/chromeos/components/tether/BUILD.gn index 1f0c4c1..fd5cc912 100644 --- a/chromeos/components/tether/BUILD.gn +++ b/chromeos/components/tether/BUILD.gn
@@ -28,6 +28,8 @@ "device_status_util.h", "disconnect_tethering_operation.cc", "disconnect_tethering_operation.h", + "host_connection_metrics_logger.cc", + "host_connection_metrics_logger.h", "host_scan_cache.cc", "host_scan_cache.h", "host_scan_device_prioritizer.h", @@ -143,6 +145,7 @@ "connect_tethering_operation_unittest.cc", "device_status_util_unittest.cc", "disconnect_tethering_operation_unittest.cc", + "host_connection_metrics_logger_unittest.cc", "host_scan_cache_unittest.cc", "host_scan_device_prioritizer_impl_unittest.cc", "host_scan_scheduler_unittest.cc",
diff --git a/chromeos/components/tether/host_connection_metrics_logger.cc b/chromeos/components/tether/host_connection_metrics_logger.cc new file mode 100644 index 0000000..4159020 --- /dev/null +++ b/chromeos/components/tether/host_connection_metrics_logger.cc
@@ -0,0 +1,116 @@ +// 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 "chromeos/components/tether/host_connection_metrics_logger.h" + +#include "base/metrics/histogram_macros.h" + +namespace chromeos { + +namespace tether { + +HostConnectionMetricsLogger::HostConnectionMetricsLogger() {} + +HostConnectionMetricsLogger::~HostConnectionMetricsLogger() {} + +void HostConnectionMetricsLogger::RecordConnectionToHostResult( + ConnectionToHostResult result) { + switch (result) { + case ConnectionToHostResult::CONNECTION_RESULT_PROVISIONING_FAILED: + RecordConnectionResultProvisioningFailure( + ConnectionToHostResult_ProvisioningFailureEventType:: + PROVISIONING_FAILED); + break; + case ConnectionToHostResult::CONNECTION_RESULT_SUCCESS: + RecordConnectionResultSuccess( + ConnectionToHostResult_SuccessEventType::SUCCESS); + break; + case ConnectionToHostResult::CONNECTION_RESULT_FAILURE_UNKNOWN_ERROR: + RecordConnectionResultFailure( + ConnectionToHostResult_FailureEventType::UNKNOWN_ERROR); + break; + case ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_CLIENT_CONNECTION_TIMEOUT: + RecordConnectionResultFailureClientConnection( + ConnectionToHostResult_FailureClientConnectionEventType::TIMEOUT); + break; + case ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_CLIENT_CONNECTION_CANCELED_BY_NEW_ATTEMPT: + RecordConnectionResultFailureClientConnection( + ConnectionToHostResult_FailureClientConnectionEventType:: + CANCELED_BY_NEW_ATTEMPT); + break; + case ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_TETHERING_TIMED_OUT_FIRST_TIME_SETUP_WAS_REQUIRED: + RecordConnectionResultFailureTetheringTimeout( + ConnectionToHostResult_FailureTetheringTimeoutEventType:: + FIRST_TIME_SETUP_WAS_REQUIRED); + break; + case ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_TETHERING_TIMED_OUT_FIRST_TIME_SETUP_WAS_NOT_REQUIRED: + RecordConnectionResultFailureTetheringTimeout( + ConnectionToHostResult_FailureTetheringTimeoutEventType:: + FIRST_TIME_SETUP_WAS_NOT_REQUIRED); + break; + default: + NOTREACHED(); + }; +} + +void HostConnectionMetricsLogger::RecordConnectionResultProvisioningFailure( + ConnectionToHostResult_ProvisioningFailureEventType event_type) { + UMA_HISTOGRAM_ENUMERATION( + "InstantTethering.ConnectionToHostResult.ProvisioningFailureRate", + event_type, + ConnectionToHostResult_ProvisioningFailureEventType:: + PROVISIONING_FAILURE_MAX); +} + +void HostConnectionMetricsLogger::RecordConnectionResultSuccess( + ConnectionToHostResult_SuccessEventType event_type) { + UMA_HISTOGRAM_ENUMERATION( + "InstantTethering.ConnectionToHostResult.SuccessRate", event_type, + ConnectionToHostResult_SuccessEventType::SUCCESS_MAX); + + RecordConnectionResultProvisioningFailure( + ConnectionToHostResult_ProvisioningFailureEventType::OTHER); +} + +void HostConnectionMetricsLogger::RecordConnectionResultFailure( + ConnectionToHostResult_FailureEventType event_type) { + UMA_HISTOGRAM_ENUMERATION( + "InstantTethering.ConnectionToHostResult.Failure", event_type, + ConnectionToHostResult_FailureEventType::FAILURE_MAX); + + RecordConnectionResultSuccess( + ConnectionToHostResult_SuccessEventType::FAILURE); +} + +void HostConnectionMetricsLogger::RecordConnectionResultFailureClientConnection( + ConnectionToHostResult_FailureClientConnectionEventType event_type) { + UMA_HISTOGRAM_ENUMERATION( + "InstantTethering.ConnectionToHostResult.Failure.ClientConnection", + event_type, + ConnectionToHostResult_FailureClientConnectionEventType:: + FAILURE_CLIENT_CONNECTION_MAX); + + RecordConnectionResultFailure( + ConnectionToHostResult_FailureEventType::CLIENT_CONNECTION_ERROR); +} + +void HostConnectionMetricsLogger::RecordConnectionResultFailureTetheringTimeout( + ConnectionToHostResult_FailureTetheringTimeoutEventType event_type) { + UMA_HISTOGRAM_ENUMERATION( + "InstantTethering.ConnectionToHostResult.Failure.TetheringTimeout", + event_type, + ConnectionToHostResult_FailureTetheringTimeoutEventType:: + FAILURE_TETHERING_TIMEOUT_MAX); + + RecordConnectionResultFailure( + ConnectionToHostResult_FailureEventType::TETHERING_TIMED_OUT); +} + +} // namespace tether + +} // namespace chromeos
diff --git a/chromeos/components/tether/host_connection_metrics_logger.h b/chromeos/components/tether/host_connection_metrics_logger.h new file mode 100644 index 0000000..f5a22ef --- /dev/null +++ b/chromeos/components/tether/host_connection_metrics_logger.h
@@ -0,0 +1,141 @@ +// 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 CHROMEOS_COMPONENTS_TETHER_HOST_CONNECTION_METRICS_LOGGER_H_ +#define CHROMEOS_COMPONENTS_TETHER_HOST_CONNECTION_METRICS_LOGGER_H_ + +#include "base/gtest_prod_util.h" +#include "base/macros.h" + +namespace chromeos { + +namespace tether { + +// Wrapper around metrics reporting for host connection results. Clients are +// expected to report the result of a host connection attempt once it has +// concluded. +class HostConnectionMetricsLogger { + public: + enum ConnectionToHostResult { + CONNECTION_RESULT_PROVISIONING_FAILED, + CONNECTION_RESULT_SUCCESS, + CONNECTION_RESULT_FAILURE_UNKNOWN_ERROR, + CONNECTION_RESULT_FAILURE_CLIENT_CONNECTION_TIMEOUT, + CONNECTION_RESULT_FAILURE_CLIENT_CONNECTION_CANCELED_BY_NEW_ATTEMPT, + CONNECTION_RESULT_FAILURE_TETHERING_TIMED_OUT_FIRST_TIME_SETUP_WAS_REQUIRED, + CONNECTION_RESULT_FAILURE_TETHERING_TIMED_OUT_FIRST_TIME_SETUP_WAS_NOT_REQUIRED + }; + + // Record the result of an attempted host connection. + virtual void RecordConnectionToHostResult(ConnectionToHostResult result); + + HostConnectionMetricsLogger(); + virtual ~HostConnectionMetricsLogger(); + + private: + friend class HostConnectionMetricsLoggerTest; + FRIEND_TEST_ALL_PREFIXES(HostConnectionMetricsLoggerTest, + RecordConnectionResultProvisioningFailure); + FRIEND_TEST_ALL_PREFIXES(HostConnectionMetricsLoggerTest, + RecordConnectionResultSuccess); + FRIEND_TEST_ALL_PREFIXES(HostConnectionMetricsLoggerTest, + RecordConnectionResultFailure); + FRIEND_TEST_ALL_PREFIXES( + HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureClientConnection_Timeout); + FRIEND_TEST_ALL_PREFIXES( + HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureClientConnection_CanceledByNewAttempt); + FRIEND_TEST_ALL_PREFIXES( + HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureTetheringTimeout_SetupRequired); + FRIEND_TEST_ALL_PREFIXES( + HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureTetheringTimeout_SetupNotRequired); + + // An Instant Tethering connection can fail for several different reasons. + // Though traditionally success and each failure case would be logged to a + // single enum, we have chosen to start at a top-level of view of simply + // "success vs failure", and then iteratively breaking down the failure count + // into its types (and possibly sub-types). Because of this cascading nature, + // when a failure sub-type occurs, the code path in question must report that + // sub-type as well as all the super-types above it. This would be cumbersome, + // and thus HostConnectionMetricsLogger exists to provide a simple API which + // handles all the other metrics that need to be reported. + // + // The most top-level metric is + // InstantTethering.ConnectionToHostResult.ProvisioningFailureRate. Its + // breakdown, and the breakdown of its subsquent metrics, is described in + // tools/metrics/histograms/histograms.xml. + enum ConnectionToHostResult_ProvisioningFailureEventType { + PROVISIONING_FAILED = 0, + OTHER = 1, + PROVISIONING_FAILURE_MAX + }; + + enum ConnectionToHostResult_SuccessEventType { + SUCCESS = 0, + FAILURE = 1, + SUCCESS_MAX + }; + + enum ConnectionToHostResult_FailureEventType { + UNKNOWN_ERROR = 0, + TETHERING_TIMED_OUT = 1, + CLIENT_CONNECTION_ERROR = 2, + FAILURE_MAX + }; + + enum ConnectionToHostResult_FailureClientConnectionEventType { + TIMEOUT = 0, + CANCELED_BY_NEW_ATTEMPT = 1, + FAILURE_CLIENT_CONNECTION_MAX + }; + + enum ConnectionToHostResult_FailureTetheringTimeoutEventType { + FIRST_TIME_SETUP_WAS_REQUIRED = 0, + FIRST_TIME_SETUP_WAS_NOT_REQUIRED = 1, + FAILURE_TETHERING_TIMEOUT_MAX + }; + + // Record if a host connection attempt never went through due to provisioning + // failure, or otherwise continued. Should only be publicly called with + // an argument of ConnectionToHostResult_ProvisioningFailureEventType::OTHER. + void RecordConnectionResultProvisioningFailure( + ConnectionToHostResult_ProvisioningFailureEventType event_type); + + // Record if a host connection attempt succeeded or failed. Should only be + // publicly called with + // an argument of ConnectionToHostResult_SuccessEventType::SUCCESS. Failure is + // covered by the RecordConnectionResultFailure() method. + void RecordConnectionResultSuccess( + ConnectionToHostResult_SuccessEventType event_type); + + // Record how a host connection attempt failed. Should only be + // publicly called with an argument of + // ConnectionToHostResult_FailureEventType::UNKNOWN_ERROR. Failure due to + // client error or tethering + // timeout is covered + // by theRecordConnectionResultFailureClientConnection() or + // RecordConnectionResultFailureTetheringTimeout() methods, respectively. + void RecordConnectionResultFailure( + ConnectionToHostResult_FailureEventType event_type); + + // Record how a host connection attempt failed due to a client error. + void RecordConnectionResultFailureClientConnection( + ConnectionToHostResult_FailureClientConnectionEventType event_type); + + // Record the conditions of when host connection attempt failed due to + // the host timing out during tethering. + void RecordConnectionResultFailureTetheringTimeout( + ConnectionToHostResult_FailureTetheringTimeoutEventType event_type); + + DISALLOW_COPY_AND_ASSIGN(HostConnectionMetricsLogger); +}; + +} // namespace tether + +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_TETHER_HOST_CONNECTION_METRICS_LOGGER_H_
diff --git a/chromeos/components/tether/host_connection_metrics_logger_unittest.cc b/chromeos/components/tether/host_connection_metrics_logger_unittest.cc new file mode 100644 index 0000000..296ecc8 --- /dev/null +++ b/chromeos/components/tether/host_connection_metrics_logger_unittest.cc
@@ -0,0 +1,189 @@ +// 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 "chromeos/components/tether/host_connection_metrics_logger.h" + +#include "base/memory/ptr_util.h" +#include "base/test/histogram_tester.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace tether { + +class HostConnectionMetricsLoggerTest : public testing::Test { + protected: + HostConnectionMetricsLoggerTest() {} + + void SetUp() override { + metrics_logger_ = base::MakeUnique<HostConnectionMetricsLogger>(); + } + + void VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType event_type) { + histogram_tester_.ExpectUniqueSample( + "InstantTethering.ConnectionToHostResult.ProvisioningFailureRate", + event_type, 1); + } + + void VerifySuccess( + HostConnectionMetricsLogger::ConnectionToHostResult_SuccessEventType + event_type) { + histogram_tester_.ExpectUniqueSample( + "InstantTethering.ConnectionToHostResult.SuccessRate", event_type, 1); + } + + void VerifyFailure( + HostConnectionMetricsLogger::ConnectionToHostResult_FailureEventType + event_type) { + histogram_tester_.ExpectUniqueSample( + "InstantTethering.ConnectionToHostResult.Failure", event_type, 1); + } + + void VerifyFailure_ClientConnection( + HostConnectionMetricsLogger:: + ConnectionToHostResult_FailureClientConnectionEventType event_type) { + histogram_tester_.ExpectUniqueSample( + "InstantTethering.ConnectionToHostResult.Failure.ClientConnection", + event_type, 1); + } + + void VerifyFailure_TetheringTimeout( + HostConnectionMetricsLogger:: + ConnectionToHostResult_FailureTetheringTimeoutEventType event_type) { + histogram_tester_.ExpectUniqueSample( + "InstantTethering.ConnectionToHostResult.Failure.TetheringTimeout", + event_type, 1); + } + + std::unique_ptr<HostConnectionMetricsLogger> metrics_logger_; + + base::HistogramTester histogram_tester_; + + private: + DISALLOW_COPY_AND_ASSIGN(HostConnectionMetricsLoggerTest); +}; + +TEST_F(HostConnectionMetricsLoggerTest, + RecordConnectionResultProvisioningFailure) { + metrics_logger_->RecordConnectionToHostResult( + HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_PROVISIONING_FAILED); + + VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType:: + PROVISIONING_FAILED); +} + +TEST_F(HostConnectionMetricsLoggerTest, RecordConnectionResultSuccess) { + metrics_logger_->RecordConnectionToHostResult( + HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_SUCCESS); + + VerifySuccess(HostConnectionMetricsLogger:: + ConnectionToHostResult_SuccessEventType::SUCCESS); + VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType::OTHER); +} + +TEST_F(HostConnectionMetricsLoggerTest, RecordConnectionResultFailure) { + metrics_logger_->RecordConnectionToHostResult( + HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_UNKNOWN_ERROR); + + VerifyFailure(HostConnectionMetricsLogger:: + ConnectionToHostResult_FailureEventType::UNKNOWN_ERROR); + + VerifySuccess(HostConnectionMetricsLogger:: + ConnectionToHostResult_SuccessEventType::FAILURE); + VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType::OTHER); +} + +TEST_F(HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureClientConnection_Timeout) { + metrics_logger_->RecordConnectionToHostResult( + HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_CLIENT_CONNECTION_TIMEOUT); + + VerifyFailure_ClientConnection( + HostConnectionMetricsLogger:: + ConnectionToHostResult_FailureClientConnectionEventType::TIMEOUT); + VerifyFailure( + HostConnectionMetricsLogger::ConnectionToHostResult_FailureEventType:: + CLIENT_CONNECTION_ERROR); + VerifySuccess(HostConnectionMetricsLogger:: + ConnectionToHostResult_SuccessEventType::FAILURE); + VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType::OTHER); +} + +TEST_F(HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureClientConnection_CanceledByNewAttempt) { + metrics_logger_->RecordConnectionToHostResult( + HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_CLIENT_CONNECTION_CANCELED_BY_NEW_ATTEMPT); + + VerifyFailure_ClientConnection( + HostConnectionMetricsLogger:: + ConnectionToHostResult_FailureClientConnectionEventType:: + CANCELED_BY_NEW_ATTEMPT); + VerifyFailure( + HostConnectionMetricsLogger::ConnectionToHostResult_FailureEventType:: + CLIENT_CONNECTION_ERROR); + VerifySuccess(HostConnectionMetricsLogger:: + ConnectionToHostResult_SuccessEventType::FAILURE); + VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType::OTHER); +} + +TEST_F(HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureTetheringTimeout_SetupRequired) { + metrics_logger_->RecordConnectionToHostResult( + HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_TETHERING_TIMED_OUT_FIRST_TIME_SETUP_WAS_REQUIRED); + + VerifyFailure_TetheringTimeout( + HostConnectionMetricsLogger:: + ConnectionToHostResult_FailureTetheringTimeoutEventType:: + FIRST_TIME_SETUP_WAS_REQUIRED); + VerifyFailure( + HostConnectionMetricsLogger::ConnectionToHostResult_FailureEventType:: + TETHERING_TIMED_OUT); + VerifySuccess(HostConnectionMetricsLogger:: + ConnectionToHostResult_SuccessEventType::FAILURE); + VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType::OTHER); +} + +TEST_F(HostConnectionMetricsLoggerTest, + RecordConnectionResultFailureTetheringTimeout_SetupNotRequired) { + metrics_logger_->RecordConnectionToHostResult( + HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_TETHERING_TIMED_OUT_FIRST_TIME_SETUP_WAS_NOT_REQUIRED); + + VerifyFailure_TetheringTimeout( + HostConnectionMetricsLogger:: + ConnectionToHostResult_FailureTetheringTimeoutEventType:: + FIRST_TIME_SETUP_WAS_NOT_REQUIRED); + VerifyFailure( + HostConnectionMetricsLogger::ConnectionToHostResult_FailureEventType:: + TETHERING_TIMED_OUT); + VerifySuccess(HostConnectionMetricsLogger:: + ConnectionToHostResult_SuccessEventType::FAILURE); + VerifyProvisioningFailure( + HostConnectionMetricsLogger:: + ConnectionToHostResult_ProvisioningFailureEventType::OTHER); +} + +} // namespace tether + +} // namespace chromeos
diff --git a/components/BUILD.gn b/components/BUILD.gn index 91a0c0e1..8024ba4 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -203,6 +203,7 @@ "//components/offline_pages/core:unit_tests", "//components/offline_pages/core/background:unit_tests", "//components/offline_pages/core/downloads:unit_tests", + "//components/offline_pages/core/prefetch:unit_tests", "//components/offline_pages/core/request_header:unit_tests", "//components/password_manager/content/browser:unit_tests", "//components/payments/content:unit_tests",
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn index ec22924..de42722 100644 --- a/components/offline_pages/core/prefetch/BUILD.gn +++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -44,6 +44,10 @@ "prefetch_service_impl.h", "prefetch_types.cc", "prefetch_types.h", + "store/prefetch_store.cc", + "store/prefetch_store.h", + "store/prefetch_store_utils.cc", + "store/prefetch_store_utils.h", "suggested_articles_observer.cc", "suggested_articles_observer.h", ] @@ -65,6 +69,7 @@ "//components/version_info", "//google_apis", "//net:net", + "//sql:sql", "//url", ] } @@ -76,6 +81,8 @@ "prefetch_request_test_base.h", "prefetch_service_test_taco.cc", "prefetch_service_test_taco.h", + "store/prefetch_store_test_util.cc", + "store/prefetch_store_test_util.h", "task_test_base.cc", "task_test_base.h", "test_offline_metrics_collector.h", @@ -96,6 +103,8 @@ "//components/prefs:test_support", "//components/version_info:channel", "//net:test_support", + "//sql:sql", + "//url", ] } @@ -111,6 +120,7 @@ source_set("unit_tests") { testonly = true sources = [ + "add_unique_urls_task_unittest.cc", "generate_page_bundle_request_unittest.cc", "generate_page_bundle_task_unittest.cc", "get_operation_request_unittest.cc", @@ -123,12 +133,14 @@ "prefetch_request_fetcher_unittest.cc", "prefetch_request_operation_response_unittest.cc", "prefetch_server_urls_unittest.cc", + "store/prefetch_store_unittest.cc", "suggested_articles_observer_unittest.cc", ] deps = [ ":prefetch", ":test_support", + "//base", "//components/download/public", "//components/gcm_driver/instance_id", "//components/offline_pages/core", @@ -137,6 +149,7 @@ "//components/variations:test_support", "//components/version_info:channel", "//net:test_support", + "//sql:sql", "//testing/gmock", "//testing/gtest", "//url",
diff --git a/components/offline_pages/core/prefetch/DEPS b/components/offline_pages/core/prefetch/DEPS index 2bebfd7..98d9dd2 100644 --- a/components/offline_pages/core/prefetch/DEPS +++ b/components/offline_pages/core/prefetch/DEPS
@@ -6,4 +6,5 @@ "+components/ntp_snippets", "+components/version_info", "+net", + "+sql", ]
diff --git a/components/offline_pages/core/prefetch/add_unique_urls_task.cc b/components/offline_pages/core/prefetch/add_unique_urls_task.cc index e25cc54..9307342 100644 --- a/components/offline_pages/core/prefetch/add_unique_urls_task.cc +++ b/components/offline_pages/core/prefetch/add_unique_urls_task.cc
@@ -4,53 +4,135 @@ #include "components/offline_pages/core/prefetch/add_unique_urls_task.h" +#include <map> #include <memory> +#include <set> #include <utility> #include "base/bind.h" #include "base/callback.h" +#include "base/time/time.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "sql/transaction.h" #include "url/gurl.h" namespace offline_pages { namespace { -// Adds new prefetch item entries to the store using the URLs and client IDs -// from |prefetch_urls| and the client's |name_space|. Also cleans up entries in -// the Zombie state from the client's |name_space| except for the ones -// whose URL is contained in |prefetch_urls|. -// Returns the number of added prefecth items. -static int AddUrlsAndCleanupZombies( - const std::string& name_space, - const std::vector<PrefetchURL>& prefetch_urls) { - NOTIMPLEMENTED(); - return 1; +std::map<std::string, std::pair<int64_t, PrefetchItemState>> +FindExistingPrefetchItemsInNamespaceSync(sql::Connection* db, + const std::string& name_space) { + static const char kSql[] = + "SELECT offline_id, state, requested_url FROM prefetch_items" + " WHERE client_namespace = ?"; + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindString(0, name_space); + + std::map<std::string, std::pair<int64_t, PrefetchItemState>> result; + while (statement.Step()) { + result.insert(std::make_pair( + statement.ColumnString(2), + std::make_pair(statement.ColumnInt64(0), static_cast<PrefetchItemState>( + statement.ColumnInt(1))))); + } + + return result; } -// TODO(fgorski): replace this with the SQL executor. -static void Execute(base::RepeatingCallback<int()> command_callback, - base::OnceCallback<void(int)> result_callback) { - std::move(result_callback).Run(command_callback.Run()); +bool CreatePrefetchItemSync(sql::Connection* db, + const std::string& name_space, + const PrefetchURL& prefetch_url) { + static const char kSql[] = + "INSERT INTO prefetch_items" + " (offline_id, requested_url, client_namespace, client_id, creation_time," + " freshness_time)" + " VALUES" + " (?, ?, ?, ?, ?, ?)"; + + int64_t now_internal = base::Time::Now().ToInternalValue(); + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt64(0, GenerateOfflineId()); + statement.BindString(1, prefetch_url.url.spec()); + statement.BindString(2, name_space); + statement.BindString(3, prefetch_url.id); + statement.BindInt64(4, now_internal); + statement.BindInt64(5, now_internal); + + return statement.Run(); +} + +// Adds new prefetch item entries to the store using the URLs and client IDs +// from |candidate_prefetch_urls| and the client's |name_space|. Also cleans up +// entries in the Zombie state from the client's |name_space| except for the +// ones whose URL is contained in |candidate_prefetch_urls|. +// Returns the number of added prefecth items. +AddUniqueUrlsTask::Result AddUrlsAndCleanupZombiesSync( + const std::string& name_space, + const std::vector<PrefetchURL>& candidate_prefetch_urls, + sql::Connection* db) { + if (!db) + return AddUniqueUrlsTask::Result::STORE_ERROR; + + sql::Transaction transaction(db); + if (!transaction.Begin()) + return AddUniqueUrlsTask::Result::STORE_ERROR; + + std::map<std::string, std::pair<int64_t, PrefetchItemState>> existing_items = + FindExistingPrefetchItemsInNamespaceSync(db, name_space); + + AddUniqueUrlsTask::Result result(AddUniqueUrlsTask::Result::NOTHING_ADDED); + for (const auto& prefetch_url : candidate_prefetch_urls) { + auto iter = existing_items.find(prefetch_url.url.spec()); + if (iter == existing_items.end()) { + if (!CreatePrefetchItemSync(db, name_space, prefetch_url)) + return AddUniqueUrlsTask::Result::STORE_ERROR; // Transaction rollback. + result = AddUniqueUrlsTask::Result::URLS_ADDED; + } else { + // Removing from the list of existing items if it was requested again, to + // prevent it from being removed in the next step. + existing_items.erase(iter); + } + } + + // Purge remaining zombie IDs. + for (const auto& existing_item : existing_items) { + if (existing_item.second.second != PrefetchItemState::ZOMBIE) + continue; + if (!DeletePrefetchItemByOfflineIdSync(db, existing_item.second.first)) + return AddUniqueUrlsTask::Result::STORE_ERROR; // Transaction rollback. + } + + if (!transaction.Commit()) + return AddUniqueUrlsTask::Result::STORE_ERROR; // Transaction rollback. + + return result; } } AddUniqueUrlsTask::AddUniqueUrlsTask( + PrefetchStore* prefetch_store, const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls) - : name_space_(name_space), + : prefetch_store_(prefetch_store), + name_space_(name_space), prefetch_urls_(prefetch_urls), weak_ptr_factory_(this) {} AddUniqueUrlsTask::~AddUniqueUrlsTask() {} void AddUniqueUrlsTask::Run() { - Execute(base::BindRepeating(&AddUrlsAndCleanupZombies, name_space_, - prefetch_urls_), - base::BindOnce(&AddUniqueUrlsTask::OnUrlsAdded, - weak_ptr_factory_.GetWeakPtr())); + prefetch_store_->Execute(base::BindOnce(&AddUrlsAndCleanupZombiesSync, + name_space_, prefetch_urls_), + base::BindOnce(&AddUniqueUrlsTask::OnUrlsAdded, + weak_ptr_factory_.GetWeakPtr())); } -void AddUniqueUrlsTask::OnUrlsAdded(int added_entry_count) { +void AddUniqueUrlsTask::OnUrlsAdded(Result result) { // TODO(carlosk): schedule NWake here if at least one new entry was added to // the store. TaskComplete();
diff --git a/components/offline_pages/core/prefetch/add_unique_urls_task.h b/components/offline_pages/core/prefetch/add_unique_urls_task.h index c265cd3b..b400915 100644 --- a/components/offline_pages/core/prefetch/add_unique_urls_task.h +++ b/components/offline_pages/core/prefetch/add_unique_urls_task.h
@@ -8,11 +8,13 @@ #include <string> #include <vector> +#include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "components/offline_pages/core/prefetch/prefetch_types.h" #include "components/offline_pages/core/task.h" namespace offline_pages { +class PrefetchStore; +struct PrefetchURL; // Task that adds new URL suggestions to the pipeline. URLs are matched against // existing ones from any stage of the process so that only new, unique ones are @@ -25,15 +27,25 @@ // from the store. class AddUniqueUrlsTask : public Task { public: - AddUniqueUrlsTask(const std::string& name_space, + // Result of executing the command in the store. + enum class Result { + NOTHING_ADDED, + URLS_ADDED, + STORE_ERROR, + }; + + AddUniqueUrlsTask(PrefetchStore* prefetch_store, + const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls); ~AddUniqueUrlsTask() override; void Run() override; private: - void OnUrlsAdded(int added_entry_count); + void OnUrlsAdded(Result result); + // Prefetch store to execute against. Not owned. + PrefetchStore* prefetch_store_; const std::string& name_space_; std::vector<PrefetchURL> prefetch_urls_;
diff --git a/components/offline_pages/core/prefetch/add_unique_urls_task_unittest.cc b/components/offline_pages/core/prefetch/add_unique_urls_task_unittest.cc new file mode 100644 index 0000000..4a9c043 --- /dev/null +++ b/components/offline_pages/core/prefetch/add_unique_urls_task_unittest.cc
@@ -0,0 +1,129 @@ +// 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/offline_pages/core/prefetch/add_unique_urls_task.h" + +#include <string> +#include <vector> + +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { +namespace { +void VerifyItemCount(int expected_count, int actual_count) { + EXPECT_EQ(expected_count, actual_count); +} +} // namespace + +class AddUniqueUrlsTaskTest : public testing::Test { + public: + AddUniqueUrlsTaskTest(); + ~AddUniqueUrlsTaskTest() override = default; + + void SetUp() override; + void TearDown() override; + + PrefetchStore* store() { return store_test_util_.store(); } + + PrefetchStoreTestUtil* store_util() { return &store_test_util_; } + + void PumpLoop(); + + private: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; + PrefetchStoreTestUtil store_test_util_; +}; + +AddUniqueUrlsTaskTest::AddUniqueUrlsTaskTest() + : task_runner_(new base::TestSimpleTaskRunner), + task_runner_handle_(task_runner_) {} + +void AddUniqueUrlsTaskTest::SetUp() { + store_test_util_.BuildStoreInMemory(); +} + +void AddUniqueUrlsTaskTest::TearDown() { + store_test_util_.DeleteStore(); + PumpLoop(); +} + +void AddUniqueUrlsTaskTest::PumpLoop() { + task_runner_->RunUntilIdle(); +} + +TEST_F(AddUniqueUrlsTaskTest, AddTaskInEmptyStore) { + std::string name_space("test"); + std::vector<PrefetchURL> urls; + urls.push_back(PrefetchURL{"ID-1", GURL("https://www.google.com/")}); + urls.push_back(PrefetchURL{"ID-2", GURL("http://www.example.com/")}); + AddUniqueUrlsTask task(store(), name_space, urls); + task.Run(); + PumpLoop(); + + store_util()->CountPrefetchItems(base::BindOnce(&VerifyItemCount, 2)); + PumpLoop(); +} + +TEST_F(AddUniqueUrlsTaskTest, DontAddURLIfItExists) { + std::string name_space("test"); + std::vector<PrefetchURL> urls; + urls.push_back(PrefetchURL{"ID-1", GURL("https://www.google.com/")}); + urls.push_back(PrefetchURL{"ID-2", GURL("http://www.example.com/")}); + AddUniqueUrlsTask task1(store(), name_space, urls); + task1.Run(); + PumpLoop(); + + urls.clear(); + urls.push_back(PrefetchURL{"ID-1", GURL("https://www.google.com/")}); + urls.push_back(PrefetchURL{"ID-3", GURL("https://news.google.com/")}); + AddUniqueUrlsTask task2(store(), name_space, urls); + task2.Run(); + PumpLoop(); + + // Do the count here. + store_util()->CountPrefetchItems(base::BindOnce(&VerifyItemCount, 3)); + PumpLoop(); +} + +TEST_F(AddUniqueUrlsTaskTest, HandleZombiePrefetchItems) { + std::string name_space("test"); + std::vector<PrefetchURL> urls; + urls.push_back(PrefetchURL{"ID-1", GURL("https://www.google.com/")}); + urls.push_back(PrefetchURL{"ID-2", GURL("http://www.example.com/")}); + urls.push_back(PrefetchURL{"ID-3", GURL("https://news.google.com/")}); + AddUniqueUrlsTask task1(store(), name_space, urls); + task1.Run(); + PumpLoop(); + + store_util()->ZombifyPrefetchItem(name_space, urls[0].url, + base::BindOnce(&VerifyItemCount, 1)); + PumpLoop(); + store_util()->ZombifyPrefetchItem(name_space, urls[1].url, + base::BindOnce(&VerifyItemCount, 1)); + PumpLoop(); + + urls.clear(); + urls.push_back(PrefetchURL{"ID-1", GURL("https://www.google.com/")}); + urls.push_back(PrefetchURL{"ID-3", GURL("https://news.google.com/")}); + urls.push_back(PrefetchURL{"ID-4", GURL("https://chrome.google.com/")}); + // ID-1 is expected to stay in zombie state. + // ID-2 is expected to be removed, because it is in zombie state. + // ID-3 is still requested, so it is ignored. + // ID-4 is added. + AddUniqueUrlsTask task2(store(), name_space, urls); + task2.Run(); + PumpLoop(); + + // Do the count here. + store_util()->CountPrefetchItems(base::BindOnce(&VerifyItemCount, 3)); + PumpLoop(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc index ce4b1fd8..04b82549 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -49,8 +49,9 @@ if (!IsPrefetchingOfflinePagesEnabled()) return; - std::unique_ptr<Task> add_task = - base::MakeUnique<AddUniqueUrlsTask>(name_space, prefetch_urls); + PrefetchStore* prefetch_store = service_->GetPrefetchStore(); + std::unique_ptr<Task> add_task = base::MakeUnique<AddUniqueUrlsTask>( + prefetch_store, name_space, prefetch_urls); task_queue_.AddTask(std::move(add_task)); // TODO(dewittj): Remove when we have proper scheduling.
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc index d324c5d..7944ff1 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
@@ -17,6 +17,8 @@ #include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" #include "components/offline_pages/core/prefetch/prefetch_service_test_taco.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" #include "components/offline_pages/core/prefetch/test_prefetch_network_request_factory.h" #include "components/version_info/channel.h" @@ -25,9 +27,10 @@ #include "url/gurl.h" namespace offline_pages { - namespace { +const std::string kTestNamespace = "TestPrefetchClientNamespace"; + class TestScopedBackgroundTask : public PrefetchDispatcher::ScopedBackgroundTask { public: @@ -45,8 +48,6 @@ class PrefetchDispatcherTest : public testing::Test { public: - const std::string TEST_NAMESPACE = "TestPrefetchClientNamespace"; - PrefetchDispatcherTest(); // Test implementation. @@ -54,6 +55,7 @@ void TearDown() override; void PumpLoop(); + PrefetchDispatcher::ScopedBackgroundTask* GetBackgroundTask() { return dispatcher_->background_task_.get(); } @@ -67,29 +69,27 @@ std::vector<PrefetchURL> test_urls_; private: - scoped_refptr<base::TestSimpleTaskRunner> task_runner_ = - new base::TestSimpleTaskRunner; + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; - OfflineEventLogger logger_; + std::unique_ptr<PrefetchServiceTestTaco> taco_; + base::test::ScopedFeatureList feature_list_; - PrefetchServiceTestTaco taco_; // Owned by |taco_|. PrefetchDispatcherImpl* dispatcher_; }; PrefetchDispatcherTest::PrefetchDispatcherTest() - : task_runner_handle_(task_runner_) { + : task_runner_(new base::TestSimpleTaskRunner), + task_runner_handle_(task_runner_) { feature_list_.InitAndEnableFeature(kPrefetchingOfflinePagesFeature); - - dispatcher_ = new PrefetchDispatcherImpl(); - taco_.SetPrefetchDispatcher(base::WrapUnique(dispatcher_)); - - taco_.CreatePrefetchService(); } void PrefetchDispatcherTest::SetUp() { - ASSERT_FALSE(task_runner()->HasPendingTask()); + dispatcher_ = new PrefetchDispatcherImpl(); + taco_.reset(new PrefetchServiceTestTaco); + taco_->SetPrefetchDispatcher(base::WrapUnique(dispatcher_)); + taco_->CreatePrefetchService(); ASSERT_TRUE(test_urls_.empty()); test_urls_.push_back({"1", GURL("http://testurl.com/foo")}); @@ -97,7 +97,9 @@ } void PrefetchDispatcherTest::TearDown() { - task_runner()->ClearPendingTasks(); + // Ensures that the store is properly disposed off. + taco_.reset(); + PumpLoop(); } void PrefetchDispatcherTest::PumpLoop() { @@ -109,7 +111,7 @@ // with the state of adding tasks, and that the end state is we have tests // that verify the proper tasks were added in the proper order at each wakeup // signal of the dispatcher. - prefetch_dispatcher()->AddCandidatePrefetchURLs(TEST_NAMESPACE, test_urls_); + prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_); prefetch_dispatcher()->RemoveAllUnprocessedPrefetchURLs( kSuggestedArticlesNamespace); prefetch_dispatcher()->RemovePrefetchURLsByClientId( @@ -117,9 +119,8 @@ } TEST_F(PrefetchDispatcherTest, AddCandidatePrefetchURLsTask) { - prefetch_dispatcher()->AddCandidatePrefetchURLs(TEST_NAMESPACE, test_urls_); + prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_); EXPECT_TRUE(dispatcher_task_queue()->HasPendingTasks()); - EXPECT_TRUE(dispatcher_task_queue()->HasRunningTask()); PumpLoop(); EXPECT_FALSE(dispatcher_task_queue()->HasPendingTasks()); EXPECT_FALSE(dispatcher_task_queue()->HasRunningTask()); @@ -132,7 +133,7 @@ // Don't add a task for new prefetch URLs. PrefetchURL prefetch_url("id", GURL("https://www.chromium.org")); prefetch_dispatcher()->AddCandidatePrefetchURLs( - TEST_NAMESPACE, std::vector<PrefetchURL>(1, prefetch_url)); + kTestNamespace, std::vector<PrefetchURL>(1, prefetch_url)); EXPECT_FALSE(dispatcher_task_queue()->HasRunningTask()); // Do nothing with a new background task.
diff --git a/components/offline_pages/core/prefetch/prefetch_downloader_unittest.cc b/components/offline_pages/core/prefetch/prefetch_downloader_unittest.cc index 9823617..1befed2 100644 --- a/components/offline_pages/core/prefetch/prefetch_downloader_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_downloader_unittest.cc
@@ -141,16 +141,23 @@ task_runner_handle_(task_runner_) {} void SetUp() override { + prefetch_service_taco_.reset(new PrefetchServiceTestTaco); + auto downloader = base::MakeUnique<PrefetchDownloader>(&download_service_, kTestChannel); download_service_.set_prefetch_downloader(downloader.get()); - prefetch_service_taco_.SetPrefetchDownloader(std::move(downloader)); + prefetch_service_taco_->SetPrefetchDownloader(std::move(downloader)); - prefetch_service_taco_.CreatePrefetchService(); + prefetch_service_taco_->CreatePrefetchService(); GetPrefetchDownloader()->SetCompletedCallback(base::Bind( &PrefetchDownloaderTest::OnDownloadCompleted, base::Unretained(this))); } + void TearDown() override { + prefetch_service_taco_.reset(); + PumpLoop(); + } + void SetDownloadServiceReady(bool ready) { download_service_.set_ready(ready); if (ready) @@ -184,13 +191,13 @@ } PrefetchDownloader* GetPrefetchDownloader() const { - return prefetch_service_taco_.prefetch_service()->GetPrefetchDownloader(); + return prefetch_service_taco_->prefetch_service()->GetPrefetchDownloader(); } scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; download::TestDownloadService download_service_; - PrefetchServiceTestTaco prefetch_service_taco_; + std::unique_ptr<PrefetchServiceTestTaco> prefetch_service_taco_; std::vector<PrefetchDownloadResult> completed_downloads_; }; @@ -209,6 +216,7 @@ std::string alt_value; EXPECT_TRUE(net::GetValueForKeyInQuery(download_url, "alt", &alt_value)); EXPECT_EQ("media", alt_value); + PumpLoop(); } TEST_F(PrefetchDownloaderTest, StartDownloadBeforeServiceReady) {
diff --git a/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc b/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc index 04f19b9a..fe969a8 100644 --- a/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc
@@ -38,21 +38,29 @@ public: PrefetchGCMAppHandlerTest() : task_runner_(new base::TestSimpleTaskRunner), - task_runner_handle_(task_runner_) { + task_runner_handle_(task_runner_) {} + + void SetUp() override { auto dispatcher = base::MakeUnique<TestPrefetchDispatcher>(); + test_dispatcher_ = dispatcher.get(); auto token_factory = base::MakeUnique<TestTokenFactory>(); token_factory_ = token_factory.get(); auto gcm_app_handler = base::MakeUnique<PrefetchGCMAppHandler>(std::move(token_factory)); - - test_dispatcher_ = dispatcher.get(); handler_ = gcm_app_handler.get(); - prefetch_service_taco_.SetPrefetchGCMHandler(std::move(gcm_app_handler)); - prefetch_service_taco_.SetPrefetchDispatcher(std::move(dispatcher)); - prefetch_service_taco_.CreatePrefetchService(); + prefetch_service_taco_.reset(new PrefetchServiceTestTaco); + prefetch_service_taco_->SetPrefetchGCMHandler(std::move(gcm_app_handler)); + prefetch_service_taco_->SetPrefetchDispatcher(std::move(dispatcher)); + prefetch_service_taco_->CreatePrefetchService(); + } + + void TearDown() override { + // Ensures that the store is properly disposed off. + prefetch_service_taco_.reset(); + task_runner_->RunUntilIdle(); } TestPrefetchDispatcher* dispatcher() { return test_dispatcher_; } @@ -62,7 +70,8 @@ private: scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; - PrefetchServiceTestTaco prefetch_service_taco_; + std::unique_ptr<PrefetchServiceTestTaco> prefetch_service_taco_; + // Owned by the taco. TestPrefetchDispatcher* test_dispatcher_; // Owned by the taco.
diff --git a/components/offline_pages/core/prefetch/prefetch_item.cc b/components/offline_pages/core/prefetch/prefetch_item.cc index 3c435bb2..375bf09 100644 --- a/components/offline_pages/core/prefetch/prefetch_item.cc +++ b/components/offline_pages/core/prefetch/prefetch_item.cc
@@ -13,9 +13,9 @@ PrefetchItem::~PrefetchItem(){}; bool PrefetchItem::operator==(const PrefetchItem& other) const { - return guid == other.guid && client_id == other.client_id && - state == other.state && url == other.url && - final_archived_url == other.final_archived_url && + return offline_id == other.offline_id && guid == other.guid && + client_id == other.client_id && state == other.state && + url == other.url && final_archived_url == other.final_archived_url && request_archive_attempt_count == other.request_archive_attempt_count && operation_name == other.operation_name && archive_body_name == other.archive_body_name &&
diff --git a/components/offline_pages/core/prefetch/prefetch_item.h b/components/offline_pages/core/prefetch/prefetch_item.h index b6b001a..ad22a92 100644 --- a/components/offline_pages/core/prefetch/prefetch_item.h +++ b/components/offline_pages/core/prefetch/prefetch_item.h
@@ -28,6 +28,10 @@ bool operator==(const PrefetchItem& other) const; bool operator!=(const PrefetchItem& other) const; + // Primary key that stays consistent between prefetch item, request and + // offline page. + int64_t offline_id = 0; + // Primary key/ID for this prefetch item (See |base::GenerateGUID()|). This // value will be reused when communicating with other systems accepting GUID // identifiers for operations linked to this item.
diff --git a/components/offline_pages/core/prefetch/prefetch_item_unittest.cc b/components/offline_pages/core/prefetch/prefetch_item_unittest.cc index e5710ea..3778281 100644 --- a/components/offline_pages/core/prefetch/prefetch_item_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
@@ -16,6 +16,11 @@ EXPECT_EQ(item1, PrefetchItem()); EXPECT_EQ(item1, PrefetchItem(item1)); + item1.offline_id = 77L; + EXPECT_NE(item1, PrefetchItem()); + EXPECT_EQ(item1, PrefetchItem(item1)); + item1 = PrefetchItem(); + item1.guid = "A"; EXPECT_NE(item1, PrefetchItem()); EXPECT_EQ(item1, PrefetchItem(item1));
diff --git a/components/offline_pages/core/prefetch/prefetch_service.h b/components/offline_pages/core/prefetch/prefetch_service.h index 10e7105..eb196b4 100644 --- a/components/offline_pages/core/prefetch/prefetch_service.h +++ b/components/offline_pages/core/prefetch/prefetch_service.h
@@ -14,6 +14,7 @@ class PrefetchDownloader; class PrefetchGCMHandler; class PrefetchNetworkRequestFactory; +class PrefetchStore; class SuggestedArticlesObserver; // Main class and entry point for the Offline Pages Prefetching feature, that @@ -33,6 +34,7 @@ virtual PrefetchGCMHandler* GetPrefetchGCMHandler() = 0; virtual PrefetchNetworkRequestFactory* GetPrefetchNetworkRequestFactory() = 0; virtual PrefetchDownloader* GetPrefetchDownloader() = 0; + virtual PrefetchStore* GetPrefetchStore() = 0; // May be |nullptr| in tests. The PrefetchService does not depend on the // SuggestedArticlesObserver, it merely owns it for lifetime purposes.
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.cc b/components/offline_pages/core/prefetch/prefetch_service_impl.cc index 478d4109..b255451 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
@@ -13,6 +13,7 @@ #include "components/offline_pages/core/prefetch/prefetch_downloader.h" #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h" #include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" namespace offline_pages { @@ -22,12 +23,14 @@ std::unique_ptr<PrefetchDispatcher> dispatcher, std::unique_ptr<PrefetchGCMHandler> gcm_handler, std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory, + std::unique_ptr<PrefetchStore> prefetch_store, std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer, std::unique_ptr<PrefetchDownloader> prefetch_downloader) : offline_metrics_collector_(std::move(offline_metrics_collector)), prefetch_dispatcher_(std::move(dispatcher)), prefetch_gcm_handler_(std::move(gcm_handler)), network_request_factory_(std::move(network_request_factory)), + prefetch_store_(std::move(prefetch_store)), suggested_articles_observer_(std::move(suggested_articles_observer)), prefetch_downloader_(std::move(prefetch_downloader)) { prefetch_dispatcher_->SetService(this); @@ -56,6 +59,10 @@ return network_request_factory_.get(); } +PrefetchStore* PrefetchServiceImpl::GetPrefetchStore() { + return prefetch_store_.get(); +} + SuggestedArticlesObserver* PrefetchServiceImpl::GetSuggestedArticlesObserver() { return suggested_articles_observer_.get(); }
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.h b/components/offline_pages/core/prefetch/prefetch_service_impl.h index 98e5d61..df8a54b 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_service_impl.h
@@ -13,12 +13,6 @@ #include "components/offline_pages/core/prefetch/prefetch_types.h" namespace offline_pages { -class OfflineMetricsCollector; -class PrefetchDispatcher; -class PrefetchDownloader; -class PrefetchGCMHandler; -class PrefetchNetworkRequestFactory; -class SuggestedArticlesObserver; class PrefetchServiceImpl : public PrefetchService { public: @@ -27,6 +21,7 @@ std::unique_ptr<PrefetchDispatcher> dispatcher, std::unique_ptr<PrefetchGCMHandler> gcm_handler, std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory, + std::unique_ptr<PrefetchStore> prefetch_store, std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer, std::unique_ptr<PrefetchDownloader> prefetch_downloader); ~PrefetchServiceImpl() override; @@ -36,6 +31,7 @@ PrefetchDispatcher* GetPrefetchDispatcher() override; PrefetchGCMHandler* GetPrefetchGCMHandler() override; PrefetchNetworkRequestFactory* GetPrefetchNetworkRequestFactory() override; + PrefetchStore* GetPrefetchStore() override; SuggestedArticlesObserver* GetSuggestedArticlesObserver() override; OfflineEventLogger* GetLogger() override; PrefetchDownloader* GetPrefetchDownloader() override; @@ -53,6 +49,7 @@ std::unique_ptr<PrefetchDispatcher> prefetch_dispatcher_; std::unique_ptr<PrefetchGCMHandler> prefetch_gcm_handler_; std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory_; + std::unique_ptr<PrefetchStore> prefetch_store_; std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer_; std::unique_ptr<PrefetchDownloader> prefetch_downloader_;
diff --git a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc index e74c98a..6296a2e 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc +++ b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
@@ -13,6 +13,8 @@ #include "components/offline_pages/core/prefetch/prefetch_downloader.h" #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h" #include "components/offline_pages/core/prefetch/prefetch_service_impl.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" #include "components/offline_pages/core/prefetch/test_offline_metrics_collector.h" #include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h" @@ -32,6 +34,10 @@ network_request_factory_ = base::MakeUnique<TestPrefetchNetworkRequestFactory>(); + PrefetchStoreTestUtil store_test_util; + store_test_util.BuildStoreInMemory(); + prefetch_store_sql_ = store_test_util.ReleaseStore(); + suggested_articles_observer_ = base::MakeUnique<SuggestedArticlesObserver>(); prefetch_downloader_ = base::WrapUnique(new PrefetchDownloader(kTestChannel)); // This sets up the testing articles as an empty vector, we can ignore the @@ -65,6 +71,12 @@ network_request_factory_ = std::move(network_request_factory); } +void PrefetchServiceTestTaco::SetPrefetchStoreSql( + std::unique_ptr<PrefetchStore> prefetch_store_sql) { + CHECK(!prefetch_service_); + prefetch_store_sql_ = std::move(prefetch_store_sql); +} + void PrefetchServiceTestTaco::SetSuggestedArticlesObserver( std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer) { CHECK(!prefetch_service_); @@ -79,12 +91,14 @@ void PrefetchServiceTestTaco::CreatePrefetchService() { CHECK(metrics_collector_ && dispatcher_ && gcm_handler_ && - suggested_articles_observer_ && network_request_factory_ && - prefetch_downloader_); + network_request_factory_ && prefetch_store_sql_ && + suggested_articles_observer_ && prefetch_downloader_); + prefetch_service_ = base::MakeUnique<PrefetchServiceImpl>( std::move(metrics_collector_), std::move(dispatcher_), std::move(gcm_handler_), std::move(network_request_factory_), - std::move(suggested_articles_observer_), std::move(prefetch_downloader_)); + std::move(prefetch_store_sql_), std::move(suggested_articles_observer_), + std::move(prefetch_downloader_)); } std::unique_ptr<PrefetchService>
diff --git a/components/offline_pages/core/prefetch/prefetch_service_test_taco.h b/components/offline_pages/core/prefetch/prefetch_service_test_taco.h index aa56544..d4db9a1 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_test_taco.h +++ b/components/offline_pages/core/prefetch/prefetch_service_test_taco.h
@@ -18,6 +18,7 @@ class PrefetchGCMHandler; class PrefetchService; class PrefetchNetworkRequestFactory; +class PrefetchStore; class SuggestedArticlesObserver; // The taco class acts as a wrapper around the prefetch service making @@ -43,6 +44,7 @@ // Default type: TestNetworkRequestFactory. void SetPrefetchNetworkRequestFactory( std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory); + void SetPrefetchStoreSql(std::unique_ptr<PrefetchStore> prefetch_store_sql); // Defaults to SuggestedArticlesObserver. Initializes the testing suggestions // by default, so no ContentSuggestionsService is required.. void SetSuggestedArticlesObserver( @@ -70,6 +72,7 @@ std::unique_ptr<PrefetchDispatcher> dispatcher_; std::unique_ptr<PrefetchGCMHandler> gcm_handler_; std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory_; + std::unique_ptr<PrefetchStore> prefetch_store_sql_; std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer_; std::unique_ptr<PrefetchDownloader> prefetch_downloader_;
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store.cc b/components/offline_pages/core/prefetch/store/prefetch_store.cc new file mode 100644 index 0000000..f6cecd57 --- /dev/null +++ b/components/offline_pages/core/prefetch/store/prefetch_store.cc
@@ -0,0 +1,173 @@ +// 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/offline_pages/core/prefetch/store/prefetch_store.h" + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/metrics/histogram_macros.h" +#include "base/sequenced_task_runner.h" +#include "base/task_runner_util.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/offline_pages/core/offline_store_types.h" +#include "components/offline_pages/core/prefetch/prefetch_item.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h" +#include "sql/connection.h" +#include "sql/meta_table.h" +#include "sql/statement.h" +#include "sql/transaction.h" + +namespace offline_pages { +namespace { + +// Name of the table with prefetch items. +const char kPrefetchItemsTableName[] = "prefetch_items"; +const char kPrefetchStoreFileName[] = "PrefetchStore.db"; + +const int kCurrentVersion = 1; +const int kCompatibleVersion = 1; + +using InitializeCallback = + base::Callback<void(InitializationStatus, + std::unique_ptr<sql::Connection>)>; + +bool CreatePrefetchItemsTable(sql::Connection* db) { + static const char kSql[] = + "CREATE TABLE prefetch_items" + "(offline_id INTEGER PRIMARY KEY NOT NULL," + " state INTEGER NOT NULL DEFAULT 0," + " request_archive_attempt_count INTEGER NOT NULL DEFAULT 0," + " archive_body_length INTEGER_NOT_NULL DEFAULT -1," + " creation_time INTEGER NOT NULL," + " freshness_time INTEGER NOT NULL," + " error_code INTEGER NOT NULL DEFAULT 0," + " guid VARCHAR NOT NULL DEFAULT ''," + " client_namespace VARCHAR NOT NULL DEFAULT ''," + " client_id VARCHAR NOT NULL DEFAULT ''," + " requested_url VARCHAR NOT NULL DEFAULT ''," + " final_archived_url VARCHAR NOT NULL DEFAULT ''," + " operation_name VARCHAR NOT NULL DEFAULT ''," + " archive_body_name VARCHAR NOT NULL DEFAULT ''" + ")"; + return db->Execute(kSql); +} + +bool CreateSchema(sql::Connection* db) { + // If you create a transaction but don't Commit() it is automatically + // rolled back by its destructor when it falls out of scope. + sql::Transaction transaction(db); + if (!transaction.Begin()) + return false; + + if (!db->DoesTableExist(kPrefetchItemsTableName)) { + if (!CreatePrefetchItemsTable(db)) + return false; + } + + sql::MetaTable meta_table; + meta_table.Init(db, kCurrentVersion, kCompatibleVersion); + + // This would be a great place to add indices when we need them. + return transaction.Commit(); +} + +bool PrepareDirectory(const base::FilePath& path) { + base::File::Error error = base::File::FILE_OK; + if (!base::DirectoryExists(path.DirName())) { + if (!base::CreateDirectoryAndGetError(path.DirName(), &error)) { + LOG(ERROR) << "Failed to create prefetch db directory: " + << base::File::ErrorToString(error); + return false; + } + } + return true; +} + +// TODO(fgorski): This function and this part of the system in general could +// benefit from a better status code reportable through UMA to better capture +// the reason for failure, aiding the process of repeated attempts to +// open/initialize the database. +bool InitializeSync(sql::Connection* db, + const base::FilePath& path, + bool in_memory) { + // These values are default. + db->set_page_size(4096); + db->set_cache_size(500); + db->set_histogram_tag("PrefetchStore"); + db->set_exclusive_locking(); + + if (!in_memory && !PrepareDirectory(path)) + return false; + + bool open_db_result = false; + if (in_memory) + open_db_result = db->OpenInMemory(); + else + open_db_result = db->Open(path); + + if (!open_db_result) { + LOG(ERROR) << "Failed to open database, in memory: " << in_memory; + return false; + } + db->Preload(); + + return CreateSchema(db); +} + +} // namespace + +PrefetchStore::PrefetchStore( + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) + : blocking_task_runner_(std::move(blocking_task_runner)), + in_memory_(true), + db_(new sql::Connection, + base::OnTaskRunnerDeleter(blocking_task_runner_)), + initialization_status_(InitializationStatus::NOT_INITIALIZED), + weak_ptr_factory_(this) {} + +PrefetchStore::PrefetchStore( + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, + const base::FilePath& path) + : blocking_task_runner_(std::move(blocking_task_runner)), + db_file_path_(path.AppendASCII(kPrefetchStoreFileName)), + in_memory_(false), + db_(new sql::Connection, + base::OnTaskRunnerDeleter(blocking_task_runner_)), + initialization_status_(InitializationStatus::NOT_INITIALIZED), + weak_ptr_factory_(this) {} + +PrefetchStore::~PrefetchStore() {} + +void PrefetchStore::Initialize(base::OnceClosure pending_command) { + DCHECK_EQ(initialization_status_, InitializationStatus::NOT_INITIALIZED); + + initialization_status_ = InitializationStatus::INITIALIZING; + base::PostTaskAndReplyWithResult( + blocking_task_runner_.get(), FROM_HERE, + base::BindOnce(&InitializeSync, db_.get(), db_file_path_, in_memory_), + base::BindOnce(&PrefetchStore::OnInitializeDone, + weak_ptr_factory_.GetWeakPtr(), + std::move(pending_command))); +} + +void PrefetchStore::OnInitializeDone(base::OnceClosure pending_command, + bool success) { + DCHECK_EQ(initialization_status_, InitializationStatus::INITIALIZING); + initialization_status_ = + success ? InitializationStatus::SUCCESS : InitializationStatus::FAILURE; + + CHECK(!pending_command.is_null()); + std::move(pending_command).Run(); + + // Once pending commands are empty, we get back to NOT_INITIALIZED state, to + // make it possible to retry initialization next time a DB operation is + // attempted. + if (initialization_status_ == InitializationStatus::FAILURE) + initialization_status_ = InitializationStatus::NOT_INITIALIZED; +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store.h b/components/offline_pages/core/prefetch/store/prefetch_store.h new file mode 100644 index 0000000..15929a6 --- /dev/null +++ b/components/offline_pages/core/prefetch/store/prefetch_store.h
@@ -0,0 +1,122 @@ +// 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_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_H_ + +#include <memory> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/location.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "base/task_runner_util.h" + +namespace sql { +class Connection; +} + +namespace offline_pages { + +enum class InitializationStatus { + NOT_INITIALIZED, + INITIALIZING, + SUCCESS, + FAILURE, +}; + +// PrefetchStore is a front end to SQLite store hosting prefetch related +// items. +// +// The store controls the pointer to the SQLite database and only makes it +// available to the |RunCallback| of the |Execute| method on the blocking +// thread. +// +// Store has a set of auxiliary functions meant to be used on the blocking +// thread. They can be found in prefetch_store_sql_utils file. +class PrefetchStore { + public: + // Definition of the callback that is going to run the core of the command in + // the |Execute| method. + template <typename T> + using RunCallback = base::OnceCallback<T(sql::Connection*)>; + + // Definition of the callback used to pass the result back to the caller of + // |Execute| method. + template <typename T> + using ResultCallback = base::OnceCallback<void(T)>; + + explicit PrefetchStore( + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); + PrefetchStore(scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, + const base::FilePath& database_dir); + ~PrefetchStore(); + + // Executes a |run_callback| on SQL store on the blocking thread, and posts + // its result back to calling thread through |result_callback|. The work will + // be postponed if the store is in NOT_INITIALIZED or INITIALIZING, in which + // case the work will have to wait until initialization is completed. Calling + // |Execute| when store is NOT_INITIALIZED will cause the store initialization + // to start. + // Store initialization status needs to be SUCCESS for test task to run, or + // FAILURE, in which case the |db| pointer passed to |run_callback| will be + // null and such case should be gracefully handled. + template <typename T> + void Execute(RunCallback<T> run_callback, ResultCallback<T> result_callback) { + CHECK_NE(initialization_status_, InitializationStatus::INITIALIZING); + + if (initialization_status_ == InitializationStatus::NOT_INITIALIZED) { + Initialize(base::BindOnce( + &PrefetchStore::Execute<T>, weak_ptr_factory_.GetWeakPtr(), + std::move(run_callback), std::move(result_callback))); + return; + } + + sql::Connection* db = + initialization_status_ == InitializationStatus::SUCCESS ? db_.get() + : nullptr; + base::PostTaskAndReplyWithResult( + blocking_task_runner_.get(), FROM_HERE, + base::BindOnce(std::move(run_callback), db), + std::move(result_callback)); + } + + // Gets the initialization status of the store. + InitializationStatus initialization_status() const { + return initialization_status_; + } + + private: + // Used internally to initialize connection. + void Initialize(base::OnceClosure pending_command); + + // Used to conclude opening/resetting DB connection. + void OnInitializeDone(base::OnceClosure pending_command, bool success); + + // Background thread where all SQL access should be run. + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; + + // Path to the database on disk. + base::FilePath db_file_path_; + + // Only open the store in memory. Used for testing. + bool in_memory_; + + // Database connection. + std::unique_ptr<sql::Connection, base::OnTaskRunnerDeleter> db_; + + // Initialization status of the store. + InitializationStatus initialization_status_; + + // Weak pointer to control the callback. + base::WeakPtrFactory<PrefetchStore> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(PrefetchStore); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_H_
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc new file mode 100644 index 0000000..b3fb7a4 --- /dev/null +++ b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
@@ -0,0 +1,90 @@ +// 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/offline_pages/core/prefetch/store/prefetch_store_test_util.h" + +#include "base/bind.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "url/gurl.h" + +namespace offline_pages { +namespace { + +int CountPrefetchItemsSync(sql::Connection* db) { + // Not starting transaction as this is a single read. + static const char kSql[] = "SELECT COUNT(offline_id) FROM prefetch_items"; + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + if (statement.Step()) + return statement.ColumnInt(0); + + return kStoreCommandFailed; +} + +int UpdateItemsStateSync(const std::string& name_space, + const std::string& url, + PrefetchItemState state, + sql::Connection* db) { + static const char kSql[] = + "UPDATE prefetch_items" + " SET state = ?" + " WHERE client_namespace = ? AND requested_url = ?"; + + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt(0, static_cast<int>(state)); + statement.BindString(1, name_space); + statement.BindString(2, url); + if (statement.Run()) + return db->GetLastChangeCount(); + + return kStoreCommandFailed; +} + +} // namespace + +PrefetchStoreTestUtil::PrefetchStoreTestUtil() {} + +PrefetchStoreTestUtil::~PrefetchStoreTestUtil() = default; + +void PrefetchStoreTestUtil::BuildStore() { + if (!temp_directory_.CreateUniqueTempDir()) + DVLOG(1) << "temp_directory_ not created"; + + store_.reset(new PrefetchStore(base::ThreadTaskRunnerHandle::Get(), + temp_directory_.GetPath())); +} + +void PrefetchStoreTestUtil::BuildStoreInMemory() { + store_.reset(new PrefetchStore(base::ThreadTaskRunnerHandle::Get())); +} + +std::unique_ptr<PrefetchStore> PrefetchStoreTestUtil::ReleaseStore() { + return std::move(store_); +} + +void PrefetchStoreTestUtil::DeleteStore() { + store_.reset(); + if (temp_directory_.IsValid()) { + if (!temp_directory_.Delete()) + DVLOG(1) << "temp_directory_ not created"; + } +} + +void PrefetchStoreTestUtil::CountPrefetchItems( + PrefetchStore::ResultCallback<int> result_callback) { + store_->Execute(base::BindOnce(&CountPrefetchItemsSync), + std::move(result_callback)); +} + +void PrefetchStoreTestUtil::ZombifyPrefetchItem( + const std::string& name_space, + const GURL& url, + PrefetchStore::ResultCallback<int> result_callback) { + store_->Execute(base::BindOnce(&UpdateItemsStateSync, name_space, url.spec(), + PrefetchItemState::ZOMBIE), + std::move(result_callback)); +} +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h new file mode 100644 index 0000000..c330308a --- /dev/null +++ b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h
@@ -0,0 +1,54 @@ +// 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_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_TEST_UTIL_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_TEST_UTIL_H_ + +#include <memory> + +#include "base/callback_forward.h" +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store.h" + +class GURL; + +namespace base { +class ScopedTempDir; +} // namespace base + +namespace offline_pages { +const int kStoreCommandFailed = -1; + +class PrefetchStoreTestUtil { + public: + PrefetchStoreTestUtil(); + ~PrefetchStoreTestUtil(); + + void BuildStore(); + void BuildStoreInMemory(); + + void CountPrefetchItems(PrefetchStore::ResultCallback<int> result_callback); + + void ZombifyPrefetchItem(const std::string& name_space, + const GURL& url, + PrefetchStore::ResultCallback<int> reuslt_callback); + + // Releases the ownership of currently controlled store. + std::unique_ptr<PrefetchStore> ReleaseStore(); + + void DeleteStore(); + + PrefetchStore* store() { return store_.get(); } + + private: + base::ScopedTempDir temp_directory_; + std::unique_ptr<PrefetchStore> store_; + + DISALLOW_COPY_AND_ASSIGN(PrefetchStoreTestUtil); +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_TEST_UTIL_H_
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_unittest.cc b/components/offline_pages/core/prefetch/store/prefetch_store_unittest.cc new file mode 100644 index 0000000..a463fce --- /dev/null +++ b/components/offline_pages/core/prefetch/store/prefetch_store_unittest.cc
@@ -0,0 +1,66 @@ +// 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/offline_pages/core/prefetch/store/prefetch_store.h" + +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "sql/transaction.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { +namespace { + +int CountPrefetchItems(sql::Connection* db) { + // Not starting transaction as this is a single read. + static const char kSql[] = "SELECT COUNT(offline_id) FROM prefetch_items"; + sql::Statement statement(db->GetUniqueStatement(kSql)); + if (statement.Step()) + return statement.ColumnInt(0); + + return -1; +} + +void CountPrefetchItemsResult(int expected_count, int actual_count) { + EXPECT_EQ(expected_count, actual_count); +} + +} // namespace + +class PrefetchStoreTest : public testing::Test { + public: + PrefetchStoreTest(); + ~PrefetchStoreTest() override = default; + + void SetUp() override { store_test_util_.BuildStoreInMemory(); } + + void TearDown() override { + store_test_util_.DeleteStore(); + PumpLoop(); + } + + PrefetchStore* store() { return store_test_util_.store(); } + + void PumpLoop() { task_runner_->RunUntilIdle(); } + + private: + PrefetchStoreTestUtil store_test_util_; + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; +}; + +PrefetchStoreTest::PrefetchStoreTest() + : task_runner_(new base::TestSimpleTaskRunner), + task_runner_handle_(task_runner_) {} + +TEST_F(PrefetchStoreTest, InitializeStore) { + store()->Execute<int>(base::BindOnce(&CountPrefetchItems), + base::BindOnce(&CountPrefetchItemsResult, 0)); + PumpLoop(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_utils.cc b/components/offline_pages/core/prefetch/store/prefetch_store_utils.cc new file mode 100644 index 0000000..e5c28d90 --- /dev/null +++ b/components/offline_pages/core/prefetch/store/prefetch_store_utils.cc
@@ -0,0 +1,29 @@ +// 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/offline_pages/core/prefetch/store/prefetch_store_utils.h" + +#include <limits> + +#include "base/rand_util.h" +#include "components/offline_pages/core/prefetch/prefetch_item.h" +#include "sql/connection.h" +#include "sql/statement.h" + +namespace offline_pages { + +int64_t GenerateOfflineId() { + return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; +} + +bool DeletePrefetchItemByOfflineIdSync(sql::Connection* db, + int64_t offline_id) { + DCHECK(db); + static const char kSql[] = "DELETE FROM prefetch_items WHERE offline_id=?"; + sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); + statement.BindInt64(0, offline_id); + return statement.Run(); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_utils.h b/components/offline_pages/core/prefetch/store/prefetch_store_utils.h new file mode 100644 index 0000000..d47696b --- /dev/null +++ b/components/offline_pages/core/prefetch/store/prefetch_store_utils.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 COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_UTILS_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_UTILS_H_ + +#include <stdint.h> + +namespace sql { +class Connection; +} // namespace sql + +namespace offline_pages { + +// Creates an offline ID for the prefetch item. +int64_t GenerateOfflineId(); + +// Deletes a prefetch item by its offline ID. Returns whether it was the item +// was successfully deleted. +bool DeletePrefetchItemByOfflineIdSync(sql::Connection* db, int64_t offline_id); + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_UTILS_H_
diff --git a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc index 5abea6c..a243c2e 100644 --- a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc +++ b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
@@ -36,17 +36,26 @@ public: OfflinePageSuggestedArticlesObserverTest() : task_runner_(new base::TestSimpleTaskRunner), - task_runner_handle_(task_runner_) { + task_runner_handle_(task_runner_) {} + + void SetUp() override { + prefetch_service_test_taco_ = base::MakeUnique<PrefetchServiceTestTaco>(); test_prefetch_dispatcher_ = new TestPrefetchDispatcher(); - prefetch_service_test_taco_.SetPrefetchDispatcher( + prefetch_service_test_taco_->SetPrefetchDispatcher( base::WrapUnique(test_prefetch_dispatcher_)); - prefetch_service_test_taco_.SetSuggestedArticlesObserver( + prefetch_service_test_taco_->SetSuggestedArticlesObserver( base::MakeUnique<SuggestedArticlesObserver>()); - prefetch_service_test_taco_.CreatePrefetchService(); + prefetch_service_test_taco_->CreatePrefetchService(); + } + + void TearDown() override { + // Ensure the store can be properly disposed off. + prefetch_service_test_taco_.reset(); + task_runner_->RunUntilIdle(); } SuggestedArticlesObserver* observer() { - return prefetch_service_test_taco_.prefetch_service() + return prefetch_service_test_taco_->prefetch_service() ->GetSuggestedArticlesObserver(); } @@ -61,7 +70,7 @@ private: scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; - PrefetchServiceTestTaco prefetch_service_test_taco_; + std::unique_ptr<PrefetchServiceTestTaco> prefetch_service_test_taco_; // Owned by the PrefetchServiceTestTaco. TestPrefetchDispatcher* test_prefetch_dispatcher_;
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index a4717e2..cf0c0718 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -85,7 +85,7 @@ delegate_->GetApplicationLocale()); state_ = base::MakeUnique<PaymentRequestState>( spec_.get(), this, delegate_->GetApplicationLocale(), - delegate_->GetPersonalDataManager(), delegate_.get()); + delegate_->GetPersonalDataManager(), delegate_.get(), &journey_logger_); return; } @@ -107,7 +107,7 @@ delegate_->GetApplicationLocale()); state_ = base::MakeUnique<PaymentRequestState>( spec_.get(), this, delegate_->GetApplicationLocale(), - delegate_->GetPersonalDataManager(), delegate_.get()); + delegate_->GetPersonalDataManager(), delegate_.get(), &journey_logger_); } void PaymentRequest::Show() {
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc index 740a4d6..1fefb16 100644 --- a/components/payments/content/payment_request_state.cc +++ b/components/payments/content/payment_request_state.cc
@@ -16,6 +16,7 @@ #include "components/autofill/core/browser/personal_data_manager.h" #include "components/payments/content/payment_response_helper.h" #include "components/payments/core/autofill_payment_instrument.h" +#include "components/payments/core/journey_logger.h" #include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_request_data_util.h" #include "components/payments/core/payment_request_delegate.h" @@ -27,13 +28,15 @@ Delegate* delegate, const std::string& app_locale, autofill::PersonalDataManager* personal_data_manager, - PaymentRequestDelegate* payment_request_delegate) + PaymentRequestDelegate* payment_request_delegate, + JourneyLogger* journey_logger) : is_ready_to_pay_(false), is_waiting_for_merchant_validation_(false), app_locale_(app_locale), spec_(spec), delegate_(delegate), personal_data_manager_(personal_data_manager), + journey_logger_(journey_logger), selected_shipping_profile_(nullptr), selected_shipping_option_error_profile_(nullptr), selected_contact_profile_(nullptr), @@ -272,12 +275,29 @@ shipping_profiles_ = profile_comparator()->FilterProfilesForShipping( raw_profiles_for_filtering); + // Set the number of suggestions shown for the sections requested by the + // merchant. + if (spec_->request_payer_name() || spec_->request_payer_phone() || + spec_->request_payer_email()) { + journey_logger_->SetNumberOfSuggestionsShown( + JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size()); + } + if (spec_->request_shipping()) { + journey_logger_->SetNumberOfSuggestionsShown( + JourneyLogger::Section::SECTION_SHIPPING_ADDRESS, + shipping_profiles_.size()); + } + // Create the list of available instruments. A copy of each card will be made // by their respective AutofillPaymentInstrument. const std::vector<autofill::CreditCard*>& cards = personal_data_manager_->GetCreditCardsToSuggest(); for (autofill::CreditCard* card : cards) AddAutofillPaymentInstrument(/*selected=*/false, *card); + + journey_logger_->SetNumberOfSuggestionsShown( + JourneyLogger::Section::SECTION_CREDIT_CARDS, + available_instruments().size()); } void PaymentRequestState::SetDefaultProfileSelections() {
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h index 19fcb35..cf25e01 100644 --- a/components/payments/content/payment_request_state.h +++ b/components/payments/content/payment_request_state.h
@@ -26,6 +26,7 @@ namespace payments { +class JourneyLogger; class PaymentInstrument; class PaymentRequestDelegate; @@ -70,7 +71,8 @@ Delegate* delegate, const std::string& app_locale, autofill::PersonalDataManager* personal_data_manager, - PaymentRequestDelegate* payment_request_delegate); + PaymentRequestDelegate* payment_request_delegate, + JourneyLogger* journey_logger); ~PaymentRequestState() override; // PaymentResponseHelper::Delegate @@ -215,10 +217,11 @@ const std::string app_locale_; - // Not owned. Never null. Both outlive this object. + // Not owned. Never null. Will outlive this object. PaymentRequestSpec* spec_; Delegate* delegate_; autofill::PersonalDataManager* personal_data_manager_; + JourneyLogger* journey_logger_; autofill::AutofillProfile* selected_shipping_profile_; autofill::AutofillProfile* selected_shipping_option_error_profile_;
diff --git a/components/payments/content/payment_request_state_unittest.cc b/components/payments/content/payment_request_state_unittest.cc index bb6c602..0e0a014 100644 --- a/components/payments/content/payment_request_state_unittest.cc +++ b/components/payments/content/payment_request_state_unittest.cc
@@ -13,6 +13,7 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/payments/content/payment_request_spec.h" +#include "components/payments/core/journey_logger.h" #include "components/payments/core/test_payment_request_delegate.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h" @@ -26,6 +27,9 @@ PaymentRequestStateTest() : num_on_selected_information_changed_called_(0), test_payment_request_delegate_(/*personal_data_manager=*/nullptr), + journey_logger_(test_payment_request_delegate_.IsIncognito(), + GURL("http://www.test.com"), + test_payment_request_delegate_.GetUkmRecorder()), address_(autofill::test::GetFullProfile()), credit_card_visa_(autofill::test::GetCreditCard()) { test_personal_data_manager_.AddTestingProfile(&address_); @@ -59,7 +63,7 @@ /*observer=*/nullptr, "en-US"); state_ = base::MakeUnique<PaymentRequestState>( spec_.get(), this, "en-US", &test_personal_data_manager_, - &test_payment_request_delegate_); + &test_payment_request_delegate_, &journey_logger_); state_->AddObserver(this); } @@ -115,6 +119,7 @@ mojom::PaymentAddressPtr selected_shipping_address_; autofill::TestPersonalDataManager test_personal_data_manager_; TestPaymentRequestDelegate test_payment_request_delegate_; + JourneyLogger journey_logger_; // Test data. autofill::AutofillProfile address_;
diff --git a/components/payments/core/journey_logger.cc b/components/payments/core/journey_logger.cc index c2170ac..bb98e356 100644 --- a/components/payments/core/journey_logger.cc +++ b/components/payments/core/journey_logger.cc
@@ -164,18 +164,15 @@ has_recorded_ = true; RecordCheckoutFlowMetrics(); - - RecordPaymentMethodMetric(); - - RecordRequestedInformationMetrics(); - - RecordSectionSpecificStats(completion_status); - - // Record the CanMakePayment metrics based on whether the transaction was - // completed or aborted by the user (UserAborted) or otherwise (OtherAborted). RecordCanMakePaymentStats(completion_status); - RecordUrlKeyedMetrics(completion_status); + + // These following metrics only make sense if the UI was shown to the user. + if (was_show_called_) { + RecordPaymentMethodMetric(); + RecordRequestedInformationMetrics(); + RecordSectionSpecificStats(completion_status); + } } void JourneyLogger::RecordCheckoutFlowMetrics() { @@ -201,10 +198,6 @@ } void JourneyLogger::RecordRequestedInformationMetrics() { - if (!was_show_called_) { - return; - } - DCHECK(requested_information_ != REQUESTED_INFORMATION_MAX); UMA_HISTOGRAM_ENUMERATION("PaymentRequest.RequestedInformation", requested_information_, REQUESTED_INFORMATION_MAX);
diff --git a/components/payments/core/journey_logger_unittest.cc b/components/payments/core/journey_logger_unittest.cc index 26211be..2fd288e 100644 --- a/components/payments/core/journey_logger_unittest.cc +++ b/components/payments/core/journey_logger_unittest.cc
@@ -439,9 +439,17 @@ JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 1); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the user completes the checkout. logger.SetCompleted(); @@ -463,9 +471,17 @@ JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 1); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the user aborts the checkout. logger.SetAborted(JourneyLogger::ABORT_REASON_ABORTED_BY_USER); @@ -487,9 +503,17 @@ JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 1); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the checkout is aborted. logger.SetAborted(JourneyLogger::ABORT_REASON_OTHER); @@ -512,9 +536,17 @@ JourneyLogger logger(/*is_incognito=*/true, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 1); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the user completes the checkout. logger.SetCompleted(); @@ -536,9 +568,17 @@ JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); - // Simulate that the user had suggestions for all the requested sections. + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + + // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 0); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the user completes the checkout. logger.SetCompleted(); @@ -561,9 +601,17 @@ JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); - // Simulate that the user had suggestions for all the requested sections. + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + + // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 0); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the user aborts the checkout. logger.SetAborted(JourneyLogger::ABORT_REASON_ABORTED_BY_USER); @@ -586,9 +634,17 @@ JourneyLogger logger(/*is_incognito=*/false, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); - // Simulate that the user had suggestions for all the requested sections. + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + + // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 0); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the the checkout is aborted. logger.SetAborted(JourneyLogger::ABORT_REASON_OTHER); @@ -612,9 +668,17 @@ JourneyLogger logger(/*is_incognito=*/true, /*url=*/GURL(""), /*ukm_recorder=*/nullptr); - // Simulate that the user had suggestions for all the requested sections. + // The merchant only requests payment information. + logger.SetRequestedInformation( + /*requested_shipping=*/false, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); + + // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_CREDIT_CARDS, 0); + // Simulate that the Payment Request was shown to the user. + logger.SetShowCalled(); + // Simulate that the user aborts the checkout. logger.SetAborted(JourneyLogger::ABORT_REASON_ABORTED_BY_USER); @@ -640,9 +704,13 @@ // Make the two loggers have different data. logger1.SetShowCalled(); - logger1.SetRequestedInformation(true, true, false, false); + logger1.SetRequestedInformation( + /*requested_shipping=*/true, /*requested_email=*/true, + /*requested_phone=*/false, /*requested_name=*/false); logger2.SetShowCalled(); - logger2.SetRequestedInformation(true, false, false, false); + logger2.SetRequestedInformation( + /*requested_shipping=*/true, /*requested_email=*/false, + /*requested_phone=*/false, /*requested_name=*/false); logger1.SetCanMakePaymentValue(true);
diff --git a/components/subresource_filter/core/common/indexed_ruleset.cc b/components/subresource_filter/core/common/indexed_ruleset.cc index d24fde53..009258e7 100644 --- a/components/subresource_filter/core/common/indexed_ruleset.cc +++ b/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -16,7 +16,7 @@ // RulesetIndexer -------------------------------------------------------------- // static -const int RulesetIndexer::kIndexedFormatVersion = 17; +const int RulesetIndexer::kIndexedFormatVersion = 18; RulesetIndexer::RulesetIndexer() : blacklist_(&builder_), whitelist_(&builder_), deactivation_(&builder_) {}
diff --git a/components/url_pattern_index/flat/url_pattern_index.fbs b/components/url_pattern_index/flat/url_pattern_index.fbs index 3a3cc7d..cb5d305a 100644 --- a/components/url_pattern_index/flat/url_pattern_index.fbs +++ b/components/url_pattern_index/flat/url_pattern_index.fbs
@@ -28,19 +28,46 @@ IS_MATCH_CASE, } +// The options controlling whether or not to activate filtering for subresources +// of documents that match the URL pattern of the rule. +// Corresponds to url_pattern_index::proto::ActivationType. +enum ActivationType : ubyte (bit_flags) { + DOCUMENT, // Disable all rules on the page. + GENERIC_BLOCK, // Disable generic URL rules on the page. +} + +// The types of subresource requests that a URL rule should be applied to. +// Corresponds to url_pattern_index::proto::ElementType. +enum ElementType : ushort (bit_flags) { + OTHER, + SCRIPT, + IMAGE, + STYLESHEET, + OBJECT, + XMLHTTPREQUEST, + // TODO(crbug.com/713774): Remove OBJECT_SUBREQUEST type once + // url_pattern_index no longer has a dependency on proto::UrlRule. + OBJECT_SUBREQUEST, + SUBDOCUMENT, + PING, + MEDIA, + FONT, + WEBSOCKET, + // Note: Update the default value for |element_types| field in UrlRule, on + // adding/removing values from this enum. +} + // The flat representation of a single URL rule. For more details regarding the // fields please see the comments to url_pattern_index::proto::UrlRule. table UrlRule { // Rule matching options, a bitmask consisting of OptionFlags. options : ubyte; - // A bitmask of element types, same as proto::UrlRule::element_types. Enables - // all element types except POPUP by default. - // Note: Keep it equal to ELEMENT_TYPE_ALL-ELEMENT_TYPE_POPUP for compactness. - element_types : ushort = 6143; + // A bitmask of ElementType. Equals ElementType_ANY by default for + // compactness. + element_types : ushort = 4095; - // A bitmask of activation types, same as proto::UrlRule::activation_types. - // Disables all activation types by default. + // A bitmask of ActivationType. Disables all activation types by default. activation_types : ubyte = 0; // Use SUBSTRING as default, since it's the most used pattern type. Same as @@ -52,6 +79,8 @@ anchor_right : AnchorType = NONE; // The list of domains to be included/excluded from the filter's affected set. + // Kept sorted for fast matching. Should either be null or have at least a + // single element. domains_included : [string]; domains_excluded : [string];
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc index c18091a..f0586d0 100644 --- a/components/url_pattern_index/url_pattern_index.cc +++ b/components/url_pattern_index/url_pattern_index.cc
@@ -8,6 +8,7 @@ #include <limits> #include <string> +#include "base/containers/flat_map.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_piece.h" @@ -25,6 +26,55 @@ using FlatDomains = flatbuffers::Vector<FlatStringOffset>; using FlatDomainsOffset = flatbuffers::Offset<FlatDomains>; +// Maps proto::ActivationType to flat::ActivationType. +const base::flat_map<proto::ActivationType, flat::ActivationType> + kActivationTypeMap( + { + {proto::ACTIVATION_TYPE_UNSPECIFIED, flat::ActivationType_NONE}, + {proto::ACTIVATION_TYPE_DOCUMENT, flat::ActivationType_DOCUMENT}, + // ELEMHIDE is not supported. + {proto::ACTIVATION_TYPE_ELEMHIDE, flat::ActivationType_NONE}, + // GENERICHIDE is not supported. + {proto::ACTIVATION_TYPE_GENERICHIDE, flat::ActivationType_NONE}, + {proto::ACTIVATION_TYPE_GENERICBLOCK, + flat::ActivationType_GENERIC_BLOCK}, + }, + base::KEEP_FIRST_OF_DUPES); + +// Maps proto::ElementType to flat::ElementType. +const base::flat_map<proto::ElementType, flat::ElementType> kElementTypeMap( + { + {proto::ELEMENT_TYPE_UNSPECIFIED, flat::ElementType_NONE}, + {proto::ELEMENT_TYPE_OTHER, flat::ElementType_OTHER}, + {proto::ELEMENT_TYPE_SCRIPT, flat::ElementType_SCRIPT}, + {proto::ELEMENT_TYPE_IMAGE, flat::ElementType_IMAGE}, + {proto::ELEMENT_TYPE_STYLESHEET, flat::ElementType_STYLESHEET}, + {proto::ELEMENT_TYPE_OBJECT, flat::ElementType_OBJECT}, + {proto::ELEMENT_TYPE_XMLHTTPREQUEST, flat::ElementType_XMLHTTPREQUEST}, + {proto::ELEMENT_TYPE_OBJECT_SUBREQUEST, + flat::ElementType_OBJECT_SUBREQUEST}, + {proto::ELEMENT_TYPE_SUBDOCUMENT, flat::ElementType_SUBDOCUMENT}, + {proto::ELEMENT_TYPE_PING, flat::ElementType_PING}, + {proto::ELEMENT_TYPE_MEDIA, flat::ElementType_MEDIA}, + {proto::ELEMENT_TYPE_FONT, flat::ElementType_FONT}, + // Filtering popups is not supported. + {proto::ELEMENT_TYPE_POPUP, flat::ElementType_NONE}, + {proto::ELEMENT_TYPE_WEBSOCKET, flat::ElementType_WEBSOCKET}, + }, + base::KEEP_FIRST_OF_DUPES); + +flat::ActivationType ProtoToFlatActivationType(proto::ActivationType type) { + const auto it = kActivationTypeMap.find(type); + DCHECK(it != kActivationTypeMap.end()); + return it->second; +} + +flat::ElementType ProtoToFlatElementType(proto::ElementType type) { + const auto it = kElementTypeMap.find(type); + DCHECK(it != kElementTypeMap.end()); + return it->second; +} + base::StringPiece ToStringPiece(const flatbuffers::String* string) { DCHECK(string); return base::StringPiece(string->c_str(), string->size()); @@ -43,6 +93,15 @@ [](char c) { return base::IsAsciiUpper(c); }); } +// Returns a bitmask of all the keys of the |map| passed. +template <typename T> +int GetKeysMask(const T& map) { + int mask = 0; + for (const auto& pair : map) + mask |= pair.first; + return mask; +} + // Checks whether a URL |rule| can be converted to its FlatBuffers equivalent, // and performs the actual conversion. class UrlRuleFlatBufferConverter { @@ -142,6 +201,9 @@ } bool InitializeOptions() { + static_assert(flat::OptionFlag_ANY <= std::numeric_limits<uint8_t>::max(), + "Option flags can not be stored in uint8_t."); + if (rule_.semantics() == proto::RULE_SEMANTICS_WHITELIST) { options_ |= flat::OptionFlag_IS_WHITELIST; } else if (rule_.semantics() != proto::RULE_SEMANTICS_BLACKLIST) { @@ -170,33 +232,41 @@ } bool InitializeElementTypes() { - static_assert( - proto::ELEMENT_TYPE_ALL <= std::numeric_limits<uint16_t>::max(), - "Element types can not be stored in uint16_t."); - element_types_ = static_cast<uint16_t>(rule_.element_types()); + static_assert(flat::ElementType_ANY <= std::numeric_limits<uint16_t>::max(), + "Element types can not be stored in uint16_t."); - // Note: Normally we can not distinguish between the main plugin resource - // and any other loads it makes. We treat them both as OBJECT requests. - if (element_types_ & proto::ELEMENT_TYPE_OBJECT_SUBREQUEST) - element_types_ |= proto::ELEMENT_TYPE_OBJECT; + // Ensure all proto::ElementType(s) are mapped in |kElementTypeMap|. + DCHECK_EQ(proto::ELEMENT_TYPE_ALL, GetKeysMask(kElementTypeMap)); - // Ignore unknown element types. - element_types_ &= proto::ELEMENT_TYPE_ALL; - // Filtering popups is not supported. - element_types_ &= ~proto::ELEMENT_TYPE_POPUP; + element_types_ = flat::ElementType_NONE; + + for (const auto& pair : kElementTypeMap) + if (rule_.element_types() & pair.first) + element_types_ |= pair.second; + + // Normally we can not distinguish between the main plugin resource and any + // other loads it makes. We treat them both as OBJECT requests. Hence an + // OBJECT request would also match OBJECT_SUBREQUEST rules, but not the + // the other way round. + if (element_types_ & flat::ElementType_OBJECT_SUBREQUEST) + element_types_ |= flat::ElementType_OBJECT; return true; } bool InitializeActivationTypes() { static_assert( - proto::ACTIVATION_TYPE_ALL <= std::numeric_limits<uint8_t>::max(), + flat::ActivationType_ANY <= std::numeric_limits<uint8_t>::max(), "Activation types can not be stored in uint8_t."); - activation_types_ = static_cast<uint8_t>(rule_.activation_types()); - // Only the following activation types are supported, ignore the others. - activation_types_ &= - proto::ACTIVATION_TYPE_DOCUMENT | proto::ACTIVATION_TYPE_GENERICBLOCK; + // Ensure all proto::ActivationType(s) are mapped in |kActivationTypeMap|. + DCHECK_EQ(proto::ACTIVATION_TYPE_ALL, GetKeysMask(kActivationTypeMap)); + + activation_types_ = flat::ActivationType_NONE; + + for (const auto& pair : kActivationTypeMap) + if (rule_.activation_types() & pair.first) + activation_types_ |= pair.second; return true; } @@ -430,21 +500,21 @@ // Returns whether the request matches flags of the specified URL |rule|. Takes // into account: -// - |element_type| of the requested resource, if not *_UNSPECIFIED. -// - |activation_type| for a subdocument request, if not *_UNSPECIFIED. +// - |element_type| of the requested resource, if not *_NONE. +// - |activation_type| for a subdocument request, if not *_NONE. // - Whether the resource |is_third_party| w.r.t. its embedding document. bool DoesRuleFlagsMatch(const flat::UrlRule& rule, - proto::ElementType element_type, - proto::ActivationType activation_type, + flat::ElementType element_type, + flat::ActivationType activation_type, bool is_third_party) { - DCHECK((element_type == proto::ELEMENT_TYPE_UNSPECIFIED) != - (activation_type == proto::ACTIVATION_TYPE_UNSPECIFIED)); + DCHECK((element_type == flat::ElementType_NONE) != + (activation_type == flat::ActivationType_NONE)); - if (element_type != proto::ELEMENT_TYPE_UNSPECIFIED && + if (element_type != flat::ElementType_NONE && !(rule.element_types() & element_type)) { return false; } - if (activation_type != proto::ACTIVATION_TYPE_UNSPECIFIED && + if (activation_type != flat::ActivationType_NONE && !(rule.activation_types() & activation_type)) { return false; } @@ -465,8 +535,8 @@ const FlatUrlRuleList* candidates, const GURL& url, const url::Origin& document_origin, - proto::ElementType element_type, - proto::ActivationType activation_type, + flat::ElementType element_type, + flat::ActivationType activation_type, bool is_third_party, bool disable_generic_rules) { if (!candidates) @@ -497,8 +567,8 @@ const flat::UrlPatternIndex& index, const GURL& url, const url::Origin& document_origin, - proto::ElementType element_type, - proto::ActivationType activation_type, + flat::ElementType element_type, + flat::ActivationType activation_type, bool is_third_party, bool disable_generic_rules) { const FlatNGramIndex* hash_table = index.ngram_index(); @@ -552,10 +622,23 @@ proto::ActivationType activation_type, bool is_third_party, bool disable_generic_rules) const { + return FindMatch(url, first_party_origin, + ProtoToFlatElementType(element_type), + ProtoToFlatActivationType(activation_type), is_third_party, + disable_generic_rules); +} + +const flat::UrlRule* UrlPatternIndexMatcher::FindMatch( + const GURL& url, + const url::Origin& first_party_origin, + flat::ElementType element_type, + flat::ActivationType activation_type, + bool is_third_party, + bool disable_generic_rules) const { if (!flat_index_ || !url.is_valid()) return nullptr; - if ((element_type == proto::ELEMENT_TYPE_UNSPECIFIED) == - (activation_type == proto::ACTIVATION_TYPE_UNSPECIFIED)) { + if ((element_type == flat::ElementType_NONE) == + (activation_type == flat::ActivationType_NONE)) { return nullptr; }
diff --git a/components/url_pattern_index/url_pattern_index.h b/components/url_pattern_index/url_pattern_index.h index 22e84b1..8f76188 100644 --- a/components/url_pattern_index/url_pattern_index.h +++ b/components/url_pattern_index/url_pattern_index.h
@@ -124,6 +124,16 @@ bool disable_generic_rules) const; private: + // Helper function to work with flat::*Type(s). If the index contains one or + // more UrlRules that match the request, returns one of them (it is undefined + // which one). Otherwise, returns nullptr. + const flat::UrlRule* FindMatch(const GURL& url, + const url::Origin& first_party_origin, + flat::ElementType element_type, + flat::ActivationType activation_type, + bool is_third_party, + bool disable_generic_rules) const; + // Must outlive this instance. const flat::UrlPatternIndex* flat_index_;
diff --git a/components/wallpaper/BUILD.gn b/components/wallpaper/BUILD.gn index 15ae1dfa..5bd8026d 100644 --- a/components/wallpaper/BUILD.gn +++ b/components/wallpaper/BUILD.gn
@@ -8,6 +8,7 @@ "wallpaper_color_calculator.h", "wallpaper_color_calculator_observer.h", "wallpaper_color_extraction_result.h", + "wallpaper_color_profile.h", "wallpaper_files_id.cc", "wallpaper_files_id.h", "wallpaper_layout.h",
diff --git a/components/wallpaper/wallpaper_color_profile.h b/components/wallpaper/wallpaper_color_profile.h new file mode 100644 index 0000000..3112eec --- /dev/null +++ b/components/wallpaper/wallpaper_color_profile.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 COMPONENTS_WALLPAPER_WALLPAPER_COLOR_PROFILE_H_ +#define COMPONENTS_WALLPAPER_WALLPAPER_COLOR_PROFILE_H_ + +namespace wallpaper { + +// The color profile type, ordered as the color profiles applied in +// ash::WallpaperController. +enum class ColorProfileType { + DARK_VIBRANT = 0, + NORMAL_VIBRANT, + LIGHT_VIBRANT, + DARK_MUTED, + NORMAL_MUTED, + LIGHT_MUTED, + + NUM_OF_COLOR_PROFILES, +}; + +} // namespace wallpaper + +#endif // COMPONENTS_WALLPAPER_WALLPAPER_COLOR_PROFILE_H_
diff --git a/content/browser/appcache/appcache_subresource_url_factory.cc b/content/browser/appcache/appcache_subresource_url_factory.cc index 70f002df..e971ba6 100644 --- a/content/browser/appcache/appcache_subresource_url_factory.cc +++ b/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -10,9 +10,9 @@ #include "content/browser/appcache/appcache_url_loader_job.h" #include "content/browser/appcache/appcache_url_loader_request.h" #include "content/browser/url_loader_factory_getter.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/resource_request.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr.h"
diff --git a/content/browser/appcache/appcache_subresource_url_factory.h b/content/browser/appcache/appcache_subresource_url_factory.h index f55afc47..a5620cf 100644 --- a/content/browser/appcache/appcache_subresource_url_factory.h +++ b/content/browser/appcache/appcache_subresource_url_factory.h
@@ -6,7 +6,7 @@ #define CONTENT_BROWSER_APPCACHE_APPCACHE_SUBRESOURCE_URL_FACTORY_H_ #include "base/memory/ref_counted.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h"
diff --git a/content/browser/appcache/appcache_url_loader_job.h b/content/browser/appcache/appcache_url_loader_job.h index f3470cb5d..42615a68 100644 --- a/content/browser/appcache/appcache_url_loader_job.h +++ b/content/browser/appcache/appcache_url_loader_job.h
@@ -16,8 +16,8 @@ #include "content/browser/appcache/appcache_storage.h" #include "content/browser/loader/url_loader_request_handler.h" #include "content/common/content_export.h" -#include "content/common/url_loader.mojom.h" #include "content/public/common/resource_request.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/data_pipe.h"
diff --git a/content/browser/blob_storage/blob_internals_url_loader.h b/content/browser/blob_storage/blob_internals_url_loader.h index 4dc9ef2..858584d9 100644 --- a/content/browser/blob_storage/blob_internals_url_loader.h +++ b/content/browser/blob_storage/blob_internals_url_loader.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_BROWSER_BLOB_STORAGE_BLOB_INTERNALS_URL_LOADER_H_ #define CONTENT_BROWSER_BLOB_STORAGE_BLOB_INTERNALS_URL_LOADER_H_ -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" namespace content { class ChromeBlobStorageContext;
diff --git a/content/browser/blob_storage/blob_url_loader_factory.cc b/content/browser/blob_storage/blob_url_loader_factory.cc index dbb2883..f9c2da3 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.cc +++ b/content/browser/blob_storage/blob_url_loader_factory.cc
@@ -13,8 +13,8 @@ #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/storage_partition_impl.h" #include "content/common/net_adapters.h" -#include "content/common/url_loader.mojom.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/io_buffer.h" #include "net/http/http_byte_range.h"
diff --git a/content/browser/blob_storage/blob_url_loader_factory.h b/content/browser/blob_storage/blob_url_loader_factory.h index 9f01143..a58effb3 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.h +++ b/content/browser/blob_storage/blob_url_loader_factory.h
@@ -9,8 +9,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "content/common/content_export.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" namespace storage {
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 20f9660d..cfda90f4 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -926,6 +926,11 @@ #endif } +gpu::GpuChannelEstablishFactory* +BrowserMainLoop::gpu_channel_establish_factory() const { + return BrowserGpuChannelHostFactory::instance(); +} + #if defined(OS_ANDROID) void BrowserMainLoop::SynchronouslyFlushStartupTasks() { startup_task_runner_->RunAllTasksNow();
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index f771cf9..7b72970 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h
@@ -43,6 +43,10 @@ class DiscardableSharedMemoryManager; } +namespace gpu { +class GpuChannelEstablishFactory; +} + namespace media { class AudioManager; class AudioSystem; @@ -170,6 +174,8 @@ return startup_trace_file_; } + gpu::GpuChannelEstablishFactory* gpu_channel_establish_factory() const; + #if defined(OS_ANDROID) void SynchronouslyFlushStartupTasks(); #endif // OS_ANDROID
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 4e735e2..e5a831c 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -21,7 +21,6 @@ #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/common/navigation_params.h" -#include "content/common/resource_request_completion_status.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/browsing_data_remover.h" @@ -35,6 +34,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/resource_devtools_info.h" #include "content/public/common/resource_request.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" #include "net/base/net_errors.h" #include "net/base/upload_bytes_element_reader.h"
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index e7f78f4..dd1dc184 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -29,7 +29,6 @@ #include "content/common/navigation_params.h" #include "content/common/page_messages.h" #include "content/common/site_isolation_policy.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" @@ -45,6 +44,7 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_constants.h" #include "content/public/common/resource_response.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "net/base/net_errors.h" #include "url/gurl.h" #include "url/url_util.h"
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 9a1a5ac..b326ec43 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -41,10 +41,10 @@ #include "content/common/frame_replication_state.h" #include "content/common/image_downloader/image_downloader.mojom.h" #include "content/common/navigation_params.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/render_frame_host.h" #include "content/public/common/javascript_dialog_type.h" #include "content/public/common/previews_state.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "device/wake_lock/public/interfaces/wake_lock_context.mojom.h" #include "media/mojo/interfaces/interface_factory.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h"
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index 62d1ae1..9c77f8a 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -182,10 +182,6 @@ } } -bool BrowserGpuChannelHostFactory::CanUseForTesting() { - return GpuDataManager::GetInstance()->GpuAccessAllowed(NULL); -} - void BrowserGpuChannelHostFactory::Initialize(bool establish_gpu_channel) { DCHECK(!instance_); instance_ = new BrowserGpuChannelHostFactory();
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index ed50f12..a2ba4d1 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -44,9 +44,6 @@ // thread stops. void CloseChannel(); - // Used to skip GpuChannelHost tests when there can be no GPU process. - static bool CanUseForTesting(); - // Overridden from gpu::GpuChannelEstablishFactory: // The factory will return a null GpuChannelHost in the callback during // shutdown.
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc index de30097..6073e19 100644 --- a/content/browser/gpu/gpu_ipc_browsertests.cc +++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -6,14 +6,15 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "build/build_config.h" +#include "content/browser/browser_main_loop.h" #include "content/browser/compositor/image_transport_factory.h" -#include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "content/browser/gpu/gpu_process_host.h" #include "content/common/gpu_stream_constants.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/browser/gpu_utils.h" #include "content/public/common/content_switches.h" #include "content/public/test/content_browser_test.h" +#include "gpu/ipc/client/gpu_channel_host.h" #include "services/ui/gpu/interfaces/gpu_service.mojom.h" #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -59,11 +60,9 @@ ~EstablishGpuChannelHelper() {} scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSyncRunLoop() { - if (!content::BrowserGpuChannelHostFactory::instance()) - content::BrowserGpuChannelHostFactory::Initialize(true); - - content::BrowserGpuChannelHostFactory* factory = - content::BrowserGpuChannelHostFactory::instance(); + gpu::GpuChannelEstablishFactory* factory = + content::BrowserMainLoop::GetInstance() + ->gpu_channel_establish_factory(); CHECK(factory); base::RunLoop run_loop; factory->EstablishGpuChannel(base::Bind( @@ -82,7 +81,7 @@ void SetUpOnMainThread() override { // This may leave the provider_ null in some cases, so tests need to early // out. - if (!content::BrowserGpuChannelHostFactory::CanUseForTesting()) + if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(nullptr)) return; EstablishGpuChannelHelper helper; @@ -124,15 +123,9 @@ class BrowserGpuChannelHostFactoryTest : public ContentBrowserTest { public: void SetUpOnMainThread() override { - if (!BrowserGpuChannelHostFactory::CanUseForTesting()) + if (!GpuDataManager::GetInstance()->GpuAccessAllowed(nullptr)) return; - - // Start all tests without a gpu channel so that the tests exercise a - // consistent codepath. - if (!BrowserGpuChannelHostFactory::instance()) - BrowserGpuChannelHostFactory::Initialize(false); CHECK(GetFactory()); - ContentBrowserTest::SetUpOnMainThread(); } @@ -155,8 +148,8 @@ } protected: - BrowserGpuChannelHostFactory* GetFactory() { - return BrowserGpuChannelHostFactory::instance(); + gpu::GpuChannelEstablishFactory* GetFactory() { + return BrowserMainLoop::GetInstance()->gpu_channel_establish_factory(); } bool IsChannelEstablished() {
diff --git a/content/browser/histogram_internals_url_loader.h b/content/browser/histogram_internals_url_loader.h index a867809..15cd781 100644 --- a/content/browser/histogram_internals_url_loader.h +++ b/content/browser/histogram_internals_url_loader.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_BROWSER_HISTOGRAM_INTERNALS_URL_LOADER_H_ #define CONTENT_BROWSER_HISTOGRAM_INTERNALS_URL_LOADER_H_ -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" namespace content {
diff --git a/content/browser/loader/DEPS b/content/browser/loader/DEPS index 3622dab2..33ce038 100644 --- a/content/browser/loader/DEPS +++ b/content/browser/loader/DEPS
@@ -29,15 +29,15 @@ # TODO: To be replaced by mojo. "+content/common/resource_messages.h", - "+content/common/resource_request_completion_status.h", "+content/common/view_messages.h", + "+content/public/common/resource_request_completion_status.h", ], "downloaded_temp_file_impl\.(cc|h)": [ "-content", "+content/browser/loader/downloaded_temp_file_impl.h", "+content/browser/loader/resource_dispatcher_host_impl.h", "+content/common/content_export.h", - "+content/common/url_loader_factory.mojom.h" + "+content/public/common/url_loader_factory.mojom.h" ], "resource_buffer.*\.(cc|h)": [ "-content", @@ -67,11 +67,11 @@ "+content/browser/loader/resource_scheduler.h", "+content/browser/loader/upload_progress_tracker.h", "+content/common/content_export.h", - "+content/common/resource_request_completion_status.h", - "+content/common/url_loader.mojom.h", "+content/public/browser/global_request_id.h", + "+content/public/common/resource_request_completion_status.h", "+content/public/common/resource_response.h", "+content/public/common/resource_type.h", + "+content/public/common/url_loader.mojom.h", ], "mojo_async_resource_handler_unittest\.cc": [ "-content", @@ -82,9 +82,6 @@ "+content/browser/loader/resource_dispatcher_host_impl.h", "+content/browser/loader/resource_request_info_impl.h", "+content/browser/loader/resource_scheduler.h", - "+content/common/resource_request_completion_status.h", - "+content/common/url_loader.mojom.h", - "+content/common/url_loader_factory.mojom.h", "+content/public/browser/appcache_service.h", "+content/public/browser/navigation_data.h", "+content/public/browser/resource_context.h", @@ -93,8 +90,11 @@ "+content/public/browser/stream_info.h", "+content/public/common/previews_state.h", "+content/public/common/resource_request.h", + "+content/public/common/resource_request_completion_status.h", "+content/public/common/resource_response.h", "+content/public/common/resource_type.h", + "+content/public/common/url_loader.mojom.h", + "+content/public/common/url_loader_factory.mojom.h", "+content/public/test/test_browser_context.h", "+content/public/test/test_browser_thread_bundle.h", ], @@ -127,7 +127,6 @@ "+content/browser/loader/throttling_resource_handler.h", "+content/browser/loader/wake_lock_resource_throttle.h", "+content/common/resource_request_body.h", - "+content/common/url_loader.mojom.h", "+content/public/browser/global_request_id.h", "+content/public/browser/resource_dispatcher_host.h", "+content/public/browser/resource_dispatcher_host_delegate.h", @@ -135,6 +134,7 @@ "+content/public/browser/resource_throttle.h", "+content/public/common/previews_state.h", "+content/public/common/resource_request_body.h", + "+content/public/common/url_loader.mojom.h", # TODO: These all have to be removed. "+content/browser/appcache/appcache_interceptor.h", @@ -180,9 +180,9 @@ # TODO: To be replaced by mojo. "+content/common/resource_messages.h", - "+content/common/resource_request_completion_status.h", "+content/common/view_messages.h", "+content/public/common/resource_request.h", + "+content/public/common/resource_request_completion_status.h", ], "resource_handler\.(cc|h)": [ "-content", @@ -230,13 +230,13 @@ "+content/browser/loader/resource_request_info_impl.h", "+content/browser/loader/resource_requester_info.h", "+content/common/content_export.h", - "+content/common/url_loader.mojom.h", "+content/public/browser/global_request_id.h", "+content/public/browser/resource_request_info.h", "+content/public/common/previews_state.h", "+content/public/common/referrer.h", "+content/public/common/resource_request_body.h", "+content/public/common/resource_type.h", + "+content/public/common/url_loader.mojom.h", # TODO: these all have to be removed. "+content/browser/frame_host/frame_tree_node.h", @@ -304,10 +304,10 @@ "test_url_loader_client\.(cc|h)": [ "-content", "+content/browser/loader/test_url_loader_client.h", - "+content/common/resource_request_completion_status.h", - "+content/common/url_loader.mojom.h", - "+content/common/url_loader_factory.mojom.h", + "+content/public/common/resource_request_completion_status.h", "+content/public/common/resource_response.h", + "+content/public/common/url_loader.mojom.h", + "+content/public/common/url_loader_factory.mojom.h", ], "upload_progress_tracker\.(cc|h)": [ "-content", @@ -320,9 +320,9 @@ "+content/browser/loader/resource_requester_info.h", "+content/browser/loader/url_loader_factory_impl.h", "+content/common/content_export.h", - "+content/common/url_loader.mojom.h", - "+content/common/url_loader_factory.mojom.h", "+content/public/common/resource_request.h", + "+content/public/common/url_loader.mojom.h", + "+content/public/common/url_loader_factory.mojom.h", ], "url_loader_factory_impl_unittest\.cc": [ "-content", @@ -334,13 +334,13 @@ "+content/browser/loader/resource_request_info_impl.h", "+content/browser/loader/url_loader_factory_impl.h", "+content/browser/loader_delegate_impl.h", - "+content/common/resource_request_completion_status.h", - "+content/common/url_loader.mojom.h", - "+content/common/url_loader_factory.mojom.h", "+content/public/browser/resource_context.h", "+content/public/browser/resource_dispatcher_host_delegate.h", "+content/public/common/content_paths.h", "+content/public/common/resource_request.h", + "+content/public/common/resource_request_completion_status.h", + "+content/public/common/url_loader.mojom.h", + "+content/public/common/url_loader_factory.mojom.h", "+content/public/test/test_browser_context.h", "+content/public/test/test_browser_thread_bundle.h",
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc index a9b2e0e..c8c8dd0 100644 --- a/content/browser/loader/async_resource_handler.cc +++ b/content/browser/loader/async_resource_handler.cc
@@ -25,8 +25,8 @@ #include "content/browser/loader/resource_request_info_impl.h" #include "content/browser/loader/upload_progress_tracker.h" #include "content/common/resource_messages.h" -#include "content/common/resource_request_completion_status.h" #include "content/common/view_messages.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" #include "ipc/ipc_message_macros.h" #include "net/base/io_buffer.h"
diff --git a/content/browser/loader/downloaded_temp_file_impl.h b/content/browser/loader/downloaded_temp_file_impl.h index 160511b..0ef0231 100644 --- a/content/browser/loader/downloaded_temp_file_impl.h +++ b/content/browser/loader/downloaded_temp_file_impl.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "content/common/content_export.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" namespace content {
diff --git a/content/browser/loader/mojo_async_resource_handler.cc b/content/browser/loader/mojo_async_resource_handler.cc index 7ec6e4a..1a84825 100644 --- a/content/browser/loader/mojo_async_resource_handler.cc +++ b/content/browser/loader/mojo_async_resource_handler.cc
@@ -23,8 +23,8 @@ #include "content/browser/loader/resource_request_info_impl.h" #include "content/browser/loader/resource_scheduler.h" #include "content/browser/loader/upload_progress_tracker.h" -#include "content/common/resource_request_completion_status.h" #include "content/public/browser/global_request_id.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/cpp/bindings/message.h"
diff --git a/content/browser/loader/mojo_async_resource_handler.h b/content/browser/loader/mojo_async_resource_handler.h index bbe3370..e139f12 100644 --- a/content/browser/loader/mojo_async_resource_handler.h +++ b/content/browser/loader/mojo_async_resource_handler.h
@@ -16,8 +16,8 @@ #include "content/browser/loader/resource_handler.h" #include "content/browser/loader/upload_progress_tracker.h" #include "content/common/content_export.h" -#include "content/common/url_loader.mojom.h" #include "content/public/common/resource_type.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/system/data_pipe.h" #include "mojo/public/cpp/system/simple_watcher.h"
diff --git a/content/browser/loader/mojo_async_resource_handler_unittest.cc b/content/browser/loader/mojo_async_resource_handler_unittest.cc index 92fdb49..1fe6c2b 100644 --- a/content/browser/loader/mojo_async_resource_handler_unittest.cc +++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -24,9 +24,6 @@ #include "content/browser/loader/resource_request_info_impl.h" #include "content/browser/loader/resource_scheduler.h" #include "content/browser/loader/test_url_loader_client.h" -#include "content/common/resource_request_completion_status.h" -#include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/appcache_service.h" #include "content/public/browser/navigation_data.h" #include "content/public/browser/resource_context.h" @@ -34,8 +31,11 @@ #include "content/public/browser/resource_throttle.h" #include "content/public/browser/stream_info.h" #include "content/public/common/previews_state.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" #include "content/public/common/resource_type.h" +#include "content/public/common/url_loader.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" #include "mojo/public/c/system/data_pipe.h"
diff --git a/content/browser/loader/navigation_url_loader_delegate.h b/content/browser/loader/navigation_url_loader_delegate.h index c31a9e0..34723cf 100644 --- a/content/browser/loader/navigation_url_loader_delegate.h +++ b/content/browser/loader/navigation_url_loader_delegate.h
@@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "content/common/content_export.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/cpp/system/data_pipe.h" namespace net {
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc index 588f30c..d558945 100644 --- a/content/browser/loader/navigation_url_loader_network_service.cc +++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -27,7 +27,6 @@ #include "content/browser/webui/url_data_manager_backend.h" #include "content/browser/webui/web_ui_url_loader_factory.h" #include "content/common/throttling_url_loader.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" @@ -38,6 +37,7 @@ #include "content/public/browser/stream_handle.h" #include "content/public/common/referrer.h" #include "content/public/common/url_constants.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "net/base/load_flags.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context.h"
diff --git a/content/browser/loader/navigation_url_loader_network_service.h b/content/browser/loader/navigation_url_loader_network_service.h index 6e57f8f..c15a4dad 100644 --- a/content/browser/loader/navigation_url_loader_network_service.h +++ b/content/browser/loader/navigation_url_loader_network_service.h
@@ -8,8 +8,8 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "content/browser/loader/navigation_url_loader.h" -#include "content/common/url_loader.mojom.h" #include "content/public/browser/ssl_status.h" +#include "content/public/common/url_loader.mojom.h" namespace net { struct RedirectInfo;
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 0ccbee7..88185f1 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -74,7 +74,6 @@ #include "content/browser/streams/stream_registry.h" #include "content/common/net/url_request_service_worker_data.h" #include "content/common/resource_messages.h" -#include "content/common/resource_request_completion_status.h" #include "content/common/site_isolation_policy.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_thread.h" @@ -91,6 +90,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/resource_request.h" #include "content/public/common/resource_request_body.h" +#include "content/public/common/resource_request_completion_status.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_message_start.h" #include "net/base/auth.h"
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index 49673ff9..0b3d32c 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -30,7 +30,6 @@ #include "content/browser/loader/global_routing_id.h" #include "content/browser/loader/resource_loader_delegate.h" #include "content/common/content_export.h" -#include "content/common/url_loader.mojom.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/resource_request_info.h" @@ -38,6 +37,7 @@ #include "content/public/common/previews_state.h" #include "content/public/common/request_context_type.h" #include "content/public/common/resource_type.h" +#include "content/public/common/url_loader.mojom.h" #include "ipc/ipc_message.h" #include "net/base/load_states.h" #include "net/base/request_priority.h"
diff --git a/content/browser/loader/resource_message_filter.h b/content/browser/loader/resource_message_filter.h index eead286..b318a552 100644 --- a/content/browser/loader/resource_message_filter.h +++ b/content/browser/loader/resource_message_filter.h
@@ -14,10 +14,10 @@ #include "base/sequenced_task_runner_helpers.h" #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/browser_associated_interface.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/common/resource_type.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace storage {
diff --git a/content/browser/loader/resource_request_info_impl.h b/content/browser/loader/resource_request_info_impl.h index e03a6876..a306acb 100644 --- a/content/browser/loader/resource_request_info_impl.h +++ b/content/browser/loader/resource_request_info_impl.h
@@ -16,13 +16,13 @@ #include "base/supports_user_data.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/loader/resource_requester_info.h" -#include "content/common/url_loader.mojom.h" #include "content/public/browser/navigation_ui_data.h" #include "content/public/browser/resource_request_info.h" #include "content/public/common/previews_state.h" #include "content/public/common/referrer.h" #include "content/public/common/resource_request_body.h" #include "content/public/common/resource_type.h" +#include "content/public/common/url_loader.mojom.h" #include "net/base/load_states.h" namespace content {
diff --git a/content/browser/loader/test_url_loader_client.h b/content/browser/loader/test_url_loader_client.h index 3e10b7a..bb5e249 100644 --- a/content/browser/loader/test_url_loader_client.h +++ b/content/browser/loader/test_url_loader_client.h
@@ -10,10 +10,10 @@ #include "base/callback.h" #include "base/macros.h" -#include "content/common/resource_request_completion_status.h" -#include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" +#include "content/public/common/url_loader.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/cpp/bindings/binding.h" #include "net/url_request/redirect_info.h"
diff --git a/content/browser/loader/url_loader_factory_impl.cc b/content/browser/loader/url_loader_factory_impl.cc index 2c82c87..2de2e1f 100644 --- a/content/browser/loader/url_loader_factory_impl.cc +++ b/content/browser/loader/url_loader_factory_impl.cc
@@ -7,8 +7,8 @@ #include "base/memory/ptr_util.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_requester_info.h" -#include "content/common/url_loader.mojom.h" #include "content/public/common/resource_request.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace content {
diff --git a/content/browser/loader/url_loader_factory_impl.h b/content/browser/loader/url_loader_factory_impl.h index 39404f7..6177975c 100644 --- a/content/browser/loader/url_loader_factory_impl.h +++ b/content/browser/loader/url_loader_factory_impl.h
@@ -9,7 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace content {
diff --git a/content/browser/loader/url_loader_factory_impl_unittest.cc b/content/browser/loader/url_loader_factory_impl_unittest.cc index a15126d..ab9dd1fc 100644 --- a/content/browser/loader/url_loader_factory_impl_unittest.cc +++ b/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -28,13 +28,13 @@ #include "content/browser/loader/resource_request_info_impl.h" #include "content/browser/loader/test_url_loader_client.h" #include "content/browser/loader_delegate_impl.h" -#include "content/common/resource_request_completion_status.h" -#include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/resource_context.h" #include "content/public/browser/resource_dispatcher_host_delegate.h" #include "content/public/common/content_paths.h" #include "content/public/common/resource_request.h" +#include "content/public/common/resource_request_completion_status.h" +#include "content/public/common/url_loader.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" #include "mojo/public/c/system/data_pipe.h"
diff --git a/content/browser/loader/url_loader_request_handler.h b/content/browser/loader/url_loader_request_handler.h index f52974c0..fb0a1f4b 100644 --- a/content/browser/loader/url_loader_request_handler.h +++ b/content/browser/loader/url_loader_request_handler.h
@@ -8,8 +8,8 @@ #include <memory> #include "base/callback_forward.h" #include "base/macros.h" -#include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" namespace content {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 6e363825..0cd9667 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -51,8 +51,8 @@ #include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "content/browser/browser_main_loop.h" #include "content/browser/compositor/surface_utils.h" -#include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" #include "content/browser/gpu/compositor_util.h" #include "content/browser/renderer_host/render_widget_host_impl.h" @@ -411,9 +411,11 @@ gpu::SharedMemoryLimits shared_memory_limits, ContextProviderCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( - base::Bind(&CreateContextProviderAfterGpuChannelEstablished, handle, - attributes, shared_memory_limits, callback)); + BrowserMainLoop::GetInstance() + ->gpu_channel_establish_factory() + ->EstablishGpuChannel( + base::Bind(&CreateContextProviderAfterGpuChannelEstablished, handle, + attributes, shared_memory_limits, callback)); } // static @@ -687,8 +689,10 @@ this, &CompositorImpl::OnGpuChannelTimeout); DCHECK(surface_handle_ != gpu::kNullSurfaceHandle); - BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(base::Bind( - &CompositorImpl::OnGpuChannelEstablished, weak_factory_.GetWeakPtr())); + BrowserMainLoop::GetInstance() + ->gpu_channel_establish_factory() + ->EstablishGpuChannel(base::Bind(&CompositorImpl::OnGpuChannelEstablished, + weak_factory_.GetWeakPtr())); } void CompositorImpl::OnGpuChannelTimeout() {
diff --git a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc index c94fe4c..697000895 100644 --- a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc +++ b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
@@ -15,10 +15,11 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" -#include "content/browser/gpu/browser_gpu_channel_host_factory.h" +#include "content/browser/browser_main_loop.h" #include "content/browser/gpu/gpu_process_host.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" +#include "gpu/ipc/client/gpu_channel_host.h" #include "media/base/media_switches.h" #include "media/base/video_frame.h" #include "media/gpu/ipc/client/gpu_jpeg_decode_accelerator_host.h" @@ -250,11 +251,12 @@ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(BrowserGpuChannelHostFactory::instance()); - BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( - base::Bind(&VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread, - task_runner, weak_this)); + BrowserMainLoop::GetInstance() + ->gpu_channel_establish_factory() + ->EstablishGpuChannel(base::Bind( + &VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread, + task_runner, weak_this)); } // static @@ -279,7 +281,7 @@ } else if (gpu_channel_host->gpu_info().jpeg_decode_accelerator_supported) { gpu_channel_host_ = std::move(gpu_channel_host); scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = - BrowserGpuChannelHostFactory::instance()->GetIOThreadTaskRunner(); + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO); int32_t route_id = gpu_channel_host_->GenerateRouteID(); std::unique_ptr<media::GpuJpegDecodeAcceleratorHost> decoder(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index e799662..d14f4113 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -139,7 +139,6 @@ #include "content/common/content_switches_internal.h" #include "content/common/frame_messages.h" #include "content/common/in_process_child_thread_params.h" -#include "content/common/network_service.mojom.h" #include "content/common/render_process_messages.h" #include "content/common/resource_messages.h" #include "content/common/service_manager/child_connection.h" @@ -164,6 +163,7 @@ #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/mojo_channel_switches.h" +#include "content/public/common/network_service.mojom.h" #include "content/public/common/process_type.h" #include "content/public/common/resource_type.h" #include "content/public/common/result_codes.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 96e664d..94a0d1f7 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -35,9 +35,9 @@ #include "content/common/renderer.mojom.h" #include "content/common/renderer_host.mojom.h" #include "content/common/storage_partition_service.mojom.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/service_manager_connection.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_platform_file.h" #include "media/media_features.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 364819d1..2c426e7 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -557,8 +557,7 @@ void RenderWidgetHostViewAura::Hide() { window_->Hide(); - // TODO(wjmaclean): can host_ ever be null? - if (host_ && !host_->is_hidden()) { + if (!host_->is_hidden()) { host_->WasHidden(); if (delegated_frame_host_) delegated_frame_host_->WasHidden(); @@ -769,7 +768,7 @@ ui::OnScreenKeyboardDisplayManager* osk_display_manager = ui::OnScreenKeyboardDisplayManager::GetInstance(); DCHECK(osk_display_manager); - if (editable && host_ && host_->GetView() && host_->delegate()) { + if (editable && host_->GetView() && host_->delegate()) { keyboard_observer_.reset(new WinScreenKeyboardObserver( host_, location_dips_screen, device_scale_factor_, window_)); virtual_keyboard_requested_ = @@ -1229,9 +1228,8 @@ } // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547 - // TODO(wjmaclean): can host_ ever be null? - if (host_ && (event_handler_->accept_return_character() || - event.GetCharacter() != ui::VKEY_RETURN)) { + if (event_handler_->accept_return_character() || + event.GetCharacter() != ui::VKEY_RETURN) { // Send a blink::WebInputEvent::Char event to |host_|. ForwardKeyboardEventWithLatencyInfo( NativeWebKeyboardEvent(event, event.GetCharacter()), *event.latency(), @@ -1404,10 +1402,6 @@ } void RenderWidgetHostViewAura::OnInputMethodChanged() { - // TODO(wjmaclean): can host_ ever be null? - if (!host_) - return; - // TODO(suzhe): implement the newly added “locale” property of HTML DOM // TextEvent. }
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h index 47bc334..fa2a126 100644 --- a/content/browser/service_worker/service_worker_fetch_dispatcher.h +++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -18,9 +18,9 @@ #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h" #include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_types.h" -#include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/common/resource_type.h" +#include "content/public/common/url_loader.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/log/net_log_with_source.h"
diff --git a/content/browser/service_worker/service_worker_url_loader_job.h b/content/browser/service_worker/service_worker_url_loader_job.h index df84f4e2..86037a2 100644 --- a/content/browser/service_worker/service_worker_url_loader_job.h +++ b/content/browser/service_worker/service_worker_url_loader_job.h
@@ -13,7 +13,7 @@ #include "content/browser/service_worker/service_worker_url_job_wrapper.h" #include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_types.h" -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/data_pipe.h" #include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_stream_handle.mojom.h"
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 9a50b97..c5798a2 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -30,9 +30,9 @@ #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/url_loader_factory_getter.h" #include "content/common/content_export.h" -#include "content/common/network_service.mojom.h" #include "content/common/storage_partition_service.mojom.h" #include "content/public/browser/storage_partition.h" +#include "content/public/common/network_service.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "net/cookies/cookie_store.h" #include "storage/browser/quota/special_storage_policy.h"
diff --git a/content/browser/url_loader_factory_getter.cc b/content/browser/url_loader_factory_getter.cc index d5013516..67cd6bac 100644 --- a/content/browser/url_loader_factory_getter.cc +++ b/content/browser/url_loader_factory_getter.cc
@@ -6,7 +6,7 @@ #include "base/bind.h" #include "content/browser/storage_partition_impl.h" -#include "content/common/network_service.mojom.h" +#include "content/public/common/network_service.mojom.h" namespace content {
diff --git a/content/browser/url_loader_factory_getter.h b/content/browser/url_loader_factory_getter.h index 1ea7281..12864590 100644 --- a/content/browser/url_loader_factory_getter.h +++ b/content/browser/url_loader_factory_getter.h
@@ -8,8 +8,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "content/common/content_export.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/url_loader_factory.mojom.h" namespace content {
diff --git a/content/browser/webui/network_error_url_loader.h b/content/browser/webui/network_error_url_loader.h index 076a6682..b4e1532 100644 --- a/content/browser/webui/network_error_url_loader.h +++ b/content/browser/webui/network_error_url_loader.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_BROWSER_WEBUI_NETWORK_ERROR_URL_LOADER_H_ #define CONTENT_BROWSER_WEBUI_NETWORK_ERROR_URL_LOADER_H_ -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" namespace content {
diff --git a/content/browser/webui/web_ui_url_loader_factory.cc b/content/browser/webui/web_ui_url_loader_factory.cc index 3e5ad0a..99bc1b30 100644 --- a/content/browser/webui/web_ui_url_loader_factory.cc +++ b/content/browser/webui/web_ui_url_loader_factory.cc
@@ -22,11 +22,11 @@ #include "content/browser/webui/network_error_url_loader.h" #include "content/browser/webui/url_data_manager_backend.h" #include "content/browser/webui/url_data_source_impl.h" -#include "content/common/network_service.mojom.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/network_service.mojom.h" #include "content/public/common/url_constants.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "third_party/zlib/google/compression_utils.h"
diff --git a/content/browser/webui/web_ui_url_loader_factory.h b/content/browser/webui/web_ui_url_loader_factory.h index b52d653..733e8e3 100644 --- a/content/browser/webui/web_ui_url_loader_factory.h +++ b/content/browser/webui/web_ui_url_loader_factory.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_BROWSER_WEBUI_WEB_UI_URL_LOADER_FACTORY_H_ #define CONTENT_BROWSER_WEBUI_WEB_UI_URL_LOADER_FACTORY_H_ -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" namespace content { class FrameTreeNode;
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index 790f652..4d724c1 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -31,12 +31,12 @@ #include "content/common/inter_process_time_ticks_converter.h" #include "content/common/navigation_params.h" #include "content/common/resource_messages.h" -#include "content/common/resource_request_completion_status.h" #include "content/common/throttling_url_loader.h" #include "content/public/child/fixed_received_data.h" #include "content/public/child/request_peer.h" #include "content/public/child/resource_dispatcher_delegate.h" #include "content/public/common/resource_request.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" #include "content/public/common/resource_type.h" #include "net/base/net_errors.h"
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h index 091bf39..fc7aa465 100644 --- a/content/child/resource_dispatcher.h +++ b/content/child/resource_dispatcher.h
@@ -22,8 +22,8 @@ #include "base/single_thread_task_runner.h" #include "base/time/time.h" #include "content/common/content_export.h" -#include "content/common/url_loader.mojom.h" #include "content/public/common/resource_type.h" +#include "content/public/common/url_loader.mojom.h" #include "content/public/common/url_loader_throttle.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h"
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc index f7a8c9e..e42b0e15 100644 --- a/content/child/resource_dispatcher_unittest.cc +++ b/content/child/resource_dispatcher_unittest.cc
@@ -24,7 +24,6 @@ #include "content/child/test_request_peer.h" #include "content/common/appcache_interfaces.h" #include "content/common/resource_messages.h" -#include "content/common/resource_request_completion_status.h" #include "content/public/child/fixed_received_data.h" #include "content/public/child/request_peer.h" #include "content/public/child/resource_dispatcher_delegate.h" @@ -32,6 +31,7 @@ #include "content/public/common/request_context_frame_type.h" #include "content/public/common/resource_request.h" #include "content/public/common/resource_request_body.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" #include "content/public/common/service_worker_modes.h" #include "net/base/net_errors.h"
diff --git a/content/child/url_loader_client_impl.h b/content/child/url_loader_client_impl.h index 872c678..16af56c 100644 --- a/content/child/url_loader_client_impl.h +++ b/content/child/url_loader_client_impl.h
@@ -11,7 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" #include "ipc/ipc_message.h" #include "mojo/public/cpp/system/data_pipe.h"
diff --git a/content/child/url_loader_client_impl_unittest.cc b/content/child/url_loader_client_impl_unittest.cc index 3ae14d5..f290cdb 100644 --- a/content/child/url_loader_client_impl_unittest.cc +++ b/content/child/url_loader_client_impl_unittest.cc
@@ -10,7 +10,7 @@ #include "base/run_loop.h" #include "content/child/resource_dispatcher.h" #include "content/child/test_request_peer.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "ipc/ipc_sender.h" #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" #include "mojo/public/cpp/bindings/binding.h"
diff --git a/content/child/url_response_body_consumer.cc b/content/child/url_response_body_consumer.cc index bce3d4e4..2766bf7 100644 --- a/content/child/url_response_body_consumer.cc +++ b/content/child/url_response_body_consumer.cc
@@ -11,8 +11,8 @@ #include "content/child/resource_dispatcher.h" #include "content/child/site_isolation_stats_gatherer.h" #include "content/common/resource_messages.h" -#include "content/common/resource_request_completion_status.h" #include "content/public/child/request_peer.h" +#include "content/public/common/resource_request_completion_status.h" namespace content {
diff --git a/content/child/url_response_body_consumer.h b/content/child/url_response_body_consumer.h index efa55dc..ecbbf0db 100644 --- a/content/child/url_response_body_consumer.h +++ b/content/child/url_response_body_consumer.h
@@ -16,7 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/system/data_pipe.h" #include "mojo/public/cpp/system/simple_watcher.h"
diff --git a/content/child/url_response_body_consumer_unittest.cc b/content/child/url_response_body_consumer_unittest.cc index be98a8e..f29fb2d3 100644 --- a/content/child/url_response_body_consumer_unittest.cc +++ b/content/child/url_response_body_consumer_unittest.cc
@@ -14,10 +14,10 @@ #include "content/child/request_extra_data.h" #include "content/child/resource_dispatcher.h" #include "content/common/resource_messages.h" -#include "content/common/resource_request_completion_status.h" #include "content/public/child/request_peer.h" #include "content/public/common/request_context_frame_type.h" #include "content/public/common/resource_request.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/service_worker_modes.h" #include "net/base/request_priority.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index 0c6e896..0da42fd 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -36,7 +36,6 @@ #include "content/child/weburlresponse_extradata_impl.h" #include "content/common/resource_messages.h" #include "content/common/service_worker/service_worker_types.h" -#include "content/common/url_loader.mojom.h" #include "content/public/child/fixed_received_data.h" #include "content/public/child/request_peer.h" #include "content/public/common/browser_side_navigation_policy.h" @@ -44,6 +43,7 @@ #include "content/public/common/resource_request.h" #include "content/public/common/resource_request_body.h" #include "content/public/common/service_worker_modes.h" +#include "content/public/common/url_loader.mojom.h" #include "net/base/data_url.h" #include "net/base/filename_util.h" #include "net/base/net_errors.h"
diff --git a/content/child/web_url_loader_impl.h b/content/child/web_url_loader_impl.h index 4fc8700..3678fa8 100644 --- a/content/child/web_url_loader_impl.h +++ b/content/child/web_url_loader_impl.h
@@ -9,8 +9,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "content/common/content_export.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/common/resource_response.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/url_request/redirect_info.h" #include "third_party/WebKit/public/platform/WebURLLoader.h"
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index e9efee7..c26f875f 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -20,7 +20,10 @@ buildflag_header("features") { header = "features.h" - flags = [ "USE_EXTERNAL_POPUP_MENU=$use_external_popup_menu" ] + flags = [ + "USE_EXTERNAL_POPUP_MENU=$use_external_popup_menu", + "ALLOW_CRITICAL_MEMORY_PRESSURE_HANDLING_IN_FOREGROUND=$allow_critical_memory_pressure_handling_in_foreground", + ] } source_set("common") { @@ -229,7 +232,6 @@ "media/video_capture.h", "message_port.cc", "message_port.h", - "mutable_network_traffic_annotation_tag_struct_traits.h", "navigation_gesture.h", "navigation_params.cc", "navigation_params.h", @@ -278,8 +280,6 @@ "resize_params.h", "resource_messages.cc", "resource_messages.h", - "resource_request_completion_status.cc", - "resource_request_completion_status.h", "sandbox_init_mac.cc", "sandbox_init_mac.h", "sandbox_init_win.cc", @@ -379,6 +379,7 @@ "//components/tracing:startup_tracing", "//content:resources", "//content/app/resources", + "//content/public/common:interfaces", "//content/public/common:service_names", "//device/base/synchronization", "//device/bluetooth", @@ -445,7 +446,10 @@ libs = [] ldflags = [] - allow_circular_includes_from = [ ":mojo_bindings" ] + allow_circular_includes_from = [ + ":mojo_bindings", + "//content/public/common:interfaces", + ] if (is_android && use_seccomp_bpf) { set_sources_assignment_filter([]) @@ -608,9 +612,7 @@ "media/media_devices.mojom", "media/renderer_audio_output_stream_factory.mojom", "memory_coordinator.mojom", - "mutable_network_traffic_annotation_tag.mojom", "native_types.mojom", - "network_service.mojom", "push_messaging.mojom", "render_frame_message_filter.mojom", "render_message_filter.mojom", @@ -624,8 +626,6 @@ "service_worker/service_worker_provider_interfaces.mojom", "service_worker/service_worker_types.mojom", "storage_partition_service.mojom", - "url_loader.mojom", - "url_loader_factory.mojom", "video_capture.mojom", "worker_url_loader_factory_provider.mojom", ]
diff --git a/content/common/features.gni b/content/common/features.gni index c43056a..b1bcb83 100644 --- a/content/common/features.gni +++ b/content/common/features.gni
@@ -2,7 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromecast_build.gni") + declare_args() { # Whether or not to use external popup menu. use_external_popup_menu = is_android || is_mac + + # Whether to perform critical memory pressure handling when in foreground (if + # false, critical memory pressure is treated like moderate pressure in foreground). + allow_critical_memory_pressure_handling_in_foreground = is_chromecast }
diff --git a/content/common/renderer_host.mojom b/content/common/renderer_host.mojom index b2a271a..8269deae 100644 --- a/content/common/renderer_host.mojom +++ b/content/common/renderer_host.mojom
@@ -4,7 +4,7 @@ module content.mojom; -import "content/common/url_loader_factory.mojom"; +import "content/public/common/url_loader_factory.mojom"; // The primordial interface implemented by a render process host. This should be // used for implementing renderer-to-browser messages.
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h index 31a5453b..0fe7c8438 100644 --- a/content/common/resource_messages.h +++ b/content/common/resource_messages.h
@@ -14,10 +14,10 @@ #include "base/process/process.h" #include "content/common/content_param_traits_macros.h" #include "content/common/navigation_params.h" -#include "content/common/resource_request_completion_status.h" #include "content/public/common/common_param_traits.h" #include "content/public/common/resource_request.h" #include "content/public/common/resource_request_body.h" +#include "content/public/common/resource_request_completion_status.h" #include "content/public/common/resource_response.h" #include "content/public/common/service_worker_modes.h" #include "ipc/ipc_message_macros.h"
diff --git a/content/common/service_worker/service_worker_event_dispatcher.mojom b/content/common/service_worker/service_worker_event_dispatcher.mojom index 93832a5..34a174c 100644 --- a/content/common/service_worker/service_worker_event_dispatcher.mojom +++ b/content/common/service_worker/service_worker_event_dispatcher.mojom
@@ -4,7 +4,7 @@ module content.mojom; -import "content/common/url_loader.mojom"; +import "content/public/common/url_loader.mojom"; import "mojo/common/string16.mojom"; import "mojo/common/time.mojom"; import "third_party/WebKit/public/platform/modules/background_sync/background_sync.mojom";
diff --git a/content/common/throttling_url_loader.h b/content/common/throttling_url_loader.h index e9f85dc..bb15aefe 100644 --- a/content/common/throttling_url_loader.h +++ b/content/common/throttling_url_loader.h
@@ -12,8 +12,8 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/common/content_export.h" #include "content/common/possibly_associated_interface_ptr.h" -#include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "content/public/common/url_loader_throttle.h" #include "mojo/public/cpp/bindings/binding.h"
diff --git a/content/common/throttling_url_loader_unittest.cc b/content/common/throttling_url_loader_unittest.cc index 3068e9ae..ac3a1fc 100644 --- a/content/common/throttling_url_loader_unittest.cc +++ b/content/common/throttling_url_loader_unittest.cc
@@ -7,8 +7,8 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "content/common/url_loader.mojom.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "content/public/common/url_loader_throttle.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/common/typemaps.gni b/content/common/typemaps.gni index 95068be3..b65fe78 100644 --- a/content/common/typemaps.gni +++ b/content/common/typemaps.gni
@@ -6,19 +6,12 @@ "//content/common/background_fetch/background_fetch_types.typemap", "//content/common/native_types.typemap", "//content/common/media/media_devices.typemap", - "//content/common/mutable_network_traffic_annotation_tag.typemap", "//content/common/push_messaging.typemap", "//content/common/service_worker/embedded_worker.typemap", "//content/common/service_worker/service_worker_event_dispatcher.typemap", "//content/common/service_worker/service_worker_fetch_request.typemap", "//content/common/service_worker/service_worker_provider.typemap", "//content/common/service_worker/service_worker_types.typemap", - "//content/common/ssl_info.typemap", - "//content/common/url_loader_status.typemap", - "//content/common/url_request.typemap", - "//content/common/url_request_redirect_info.typemap", - "//content/common/url_response_head.typemap", - "//content/common/url_sync_load_result.typemap", "//content/common/web_preferences.typemap", "//content/common/media/media_session.typemap", ]
diff --git a/content/common/url_request_struct_traits.h b/content/common/url_request_struct_traits.h index 3aecba8..0326632 100644 --- a/content/common/url_request_struct_traits.h +++ b/content/common/url_request_struct_traits.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_COMMON_URL_REQUEST_STRUCT_TRAITS_H_ #define CONTENT_COMMON_URL_REQUEST_STRUCT_TRAITS_H_ -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/bindings/enum_traits.h" #include "net/base/request_priority.h"
diff --git a/content/common/worker_url_loader_factory_provider.mojom b/content/common/worker_url_loader_factory_provider.mojom index 6590e4f..71a4956 100644 --- a/content/common/worker_url_loader_factory_provider.mojom +++ b/content/common/worker_url_loader_factory_provider.mojom
@@ -4,7 +4,7 @@ module content.mojom; -import "url_loader_factory.mojom"; +import "content/public/common/url_loader_factory.mojom"; // A renderer-side interface that is returned by CreateWorkerFetchContext for // the browser to notify the renderer process when there's a controller change.
diff --git a/content/network/DEPS b/content/network/DEPS index 935a07d..ac2ce4d 100644 --- a/content/network/DEPS +++ b/content/network/DEPS
@@ -4,16 +4,16 @@ "-content", "+content/common/content_export.h", "+content/common/net_adapters.h", - "+content/common/network_service.mojom.h", - "+content/common/url_loader.mojom.h", - "+content/common/url_loader_factory.mojom.h", "+content/network", "+content/public/common/content_client.h", "+content/public/common/content_switches.h", + "+content/public/common/network_service.mojom.h", "+content/public/common/referrer.h", "+content/public/common/resource_request.h", "+content/public/common/resource_response.h", "+content/public/common/url_constants.h", + "+content/public/common/url_loader.mojom.h", + "+content/public/common/url_loader_factory.mojom.h", "+services/service_manager/public", ]
diff --git a/content/network/cache_url_loader.h b/content/network/cache_url_loader.h index a4e1521..28d9d4b 100644 --- a/content/network/cache_url_loader.h +++ b/content/network/cache_url_loader.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_NETWORK_CACHE_URL_LOADER_H_ #define CONTENT_NETWORK_CACHE_URL_LOADER_H_ -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" namespace net { class URLRequestContext;
diff --git a/content/network/network_context.h b/content/network/network_context.h index b6b5332f..278923f 100644 --- a/content/network/network_context.h +++ b/content/network/network_context.h
@@ -12,8 +12,8 @@ #include "base/macros.h" #include "content/common/content_export.h" -#include "content/common/network_service.mojom.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/network_service.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/strong_binding_set.h"
diff --git a/content/network/network_service.h b/content/network/network_service.h index c945b9ad..703ffc2 100644 --- a/content/network/network_service.h +++ b/content/network/network_service.h
@@ -9,7 +9,7 @@ #include "base/macros.h" #include "content/common/content_export.h" -#include "content/common/network_service.mojom.h" +#include "content/public/common/network_service.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service.h"
diff --git a/content/network/network_service_unittest.cc b/content/network/network_service_unittest.cc index 398808c6..29aa109 100644 --- a/content/network/network_service_unittest.cc +++ b/content/network/network_service_unittest.cc
@@ -7,9 +7,9 @@ #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/common/network_service.mojom.h" #include "content/network/network_context.h" #include "content/network/network_service.h" +#include "content/public/common/network_service.mojom.h" #include "testing/gtest/include/gtest/gtest.h" namespace content {
diff --git a/content/network/network_service_url_loader_factory_impl.h b/content/network/network_service_url_loader_factory_impl.h index 1c22d25b..8518717 100644 --- a/content/network/network_service_url_loader_factory_impl.h +++ b/content/network/network_service_url_loader_factory_impl.h
@@ -6,7 +6,7 @@ #define CONTENT_NETWORK_NETWORK_SERVICE_URL_LOADER_FACTORY_IMPL_H_ #include "base/macros.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace content {
diff --git a/content/network/url_loader_impl.cc b/content/network/url_loader_impl.cc index 6ecf2b73..5b86d6e 100644 --- a/content/network/url_loader_impl.cc +++ b/content/network/url_loader_impl.cc
@@ -8,10 +8,10 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "content/common/net_adapters.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/network/network_context.h" #include "content/public/common/referrer.h" #include "content/public/common/resource_response.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/load_flags.h" #include "net/base/upload_bytes_element_reader.h"
diff --git a/content/network/url_loader_impl.h b/content/network/url_loader_impl.h index b23f2f6d..df0211b 100644 --- a/content/network/url_loader_impl.h +++ b/content/network/url_loader_impl.h
@@ -11,7 +11,7 @@ #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" -#include "content/common/url_loader.mojom.h" +#include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/system/simple_watcher.h" #include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index 0e20d7f5..2ce68b81d 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -170,6 +170,7 @@ "mhtml_generation_params.h", "mojo_channel_switches.cc", "mojo_channel_switches.h", + "mutable_network_traffic_annotation_tag_struct_traits.h", "notification_resources.cc", "notification_resources.h", "origin_trial_policy.cc", @@ -208,6 +209,8 @@ "resource_request.h", "resource_request_body.cc", "resource_request_body.h", + "resource_request_completion_status.cc", + "resource_request_completion_status.h", "resource_response.cc", "resource_response.h", "resource_response_info.cc", @@ -259,9 +262,9 @@ public_configs = [ "//v8:external_startup_data" ] public_deps = [ + ":interfaces", ":service_names", "//content/common", - "//content/public/common:interfaces", "//ipc", "//mojo/edk/system", "//mojo/public/cpp/bindings", @@ -304,6 +307,7 @@ # //content/common needs to include public headers. allow_circular_includes_from = [ + ":interfaces", "//content/common", "//content/common:mojo_bindings", ] @@ -341,10 +345,31 @@ } mojom("interfaces") { + # Must depend on //content/public/common/ instead, for component build. + visibility = [ + ":common_sources", + "//content/common/*", + ] + sources = [ + "mutable_network_traffic_annotation_tag.mojom", + "network_service.mojom", "network_service_test.mojom", + "url_loader.mojom", + "url_loader_factory.mojom", "window_container_type.mojom", ] + + public_deps = [ + "//mojo/common:common_custom_types", + "//url/mojo:url_mojom_gurl", + "//url/mojo:url_mojom_origin", + ] + + component_output_prefix = "content_public_common_mojo_bindings" + export_class_attribute = "CONTENT_EXPORT" + export_define = "CONTENT_IMPLEMENTATION=1" + export_header = "content/common/content_export.h" } mojom("service_names") {
diff --git a/content/common/mutable_network_traffic_annotation_tag.mojom b/content/public/common/mutable_network_traffic_annotation_tag.mojom similarity index 100% rename from content/common/mutable_network_traffic_annotation_tag.mojom rename to content/public/common/mutable_network_traffic_annotation_tag.mojom
diff --git a/content/common/mutable_network_traffic_annotation_tag.typemap b/content/public/common/mutable_network_traffic_annotation_tag.typemap similarity index 63% rename from content/common/mutable_network_traffic_annotation_tag.typemap rename to content/public/common/mutable_network_traffic_annotation_tag.typemap index dd9917d..986566b1 100644 --- a/content/common/mutable_network_traffic_annotation_tag.typemap +++ b/content/public/common/mutable_network_traffic_annotation_tag.typemap
@@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//content/common/mutable_network_traffic_annotation_tag.mojom" -traits_headers = [ "//content/common/mutable_network_traffic_annotation_tag_struct_traits.h" ] +mojom = "//content/public/common/mutable_network_traffic_annotation_tag.mojom" +traits_headers = [ "//content/public/common/mutable_network_traffic_annotation_tag_struct_traits.h" ] deps = [ "//net:traffic_annotation", ]
diff --git a/content/common/mutable_network_traffic_annotation_tag_struct_traits.h b/content/public/common/mutable_network_traffic_annotation_tag_struct_traits.h similarity index 72% rename from content/common/mutable_network_traffic_annotation_tag_struct_traits.h rename to content/public/common/mutable_network_traffic_annotation_tag_struct_traits.h index 55f9207..d17df8b 100644 --- a/content/common/mutable_network_traffic_annotation_tag_struct_traits.h +++ b/content/public/common/mutable_network_traffic_annotation_tag_struct_traits.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_COMMON_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_PARAM_TRAITS_H_ -#define CONTENT_COMMON_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_PARAM_TRAITS_H_ +#ifndef CONTENT_PUBLIC_COMMON_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_PARAM_TRAITS_H_ +#define CONTENT_PUBLIC_COMMON_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_PARAM_TRAITS_H_ -#include "content/common/mutable_network_traffic_annotation_tag.mojom.h" +#include "content/public/common/mutable_network_traffic_annotation_tag.mojom.h" #include "mojo/common/common_custom_types_struct_traits.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -28,4 +28,4 @@ } // namespace mojo -#endif // CONTENT_COMMON_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_PARAM_TRAITS_H_ +#endif // CONTENT_PUBLIC_COMMON_MUTABLE_NETWORK_TRAFFIC_ANNOTATION_PARAM_TRAITS_H_
diff --git a/content/common/network_service.mojom b/content/public/common/network_service.mojom similarity index 100% rename from content/common/network_service.mojom rename to content/public/common/network_service.mojom
diff --git a/content/common/resource_request_completion_status.cc b/content/public/common/resource_request_completion_status.cc similarity index 91% rename from content/common/resource_request_completion_status.cc rename to content/public/common/resource_request_completion_status.cc index 3720d24f..2056851 100644 --- a/content/common/resource_request_completion_status.cc +++ b/content/public/common/resource_request_completion_status.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/common/resource_request_completion_status.h" +#include "content/public/common/resource_request_completion_status.h" #include "net/base/net_errors.h"
diff --git a/content/common/resource_request_completion_status.h b/content/public/common/resource_request_completion_status.h similarity index 86% rename from content/common/resource_request_completion_status.h rename to content/public/common/resource_request_completion_status.h index 073704e2..2a50977 100644 --- a/content/common/resource_request_completion_status.h +++ b/content/public/common/resource_request_completion_status.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_COMMON_RESOURCE_REQUEST_COMPLETION_STATUS_H_ -#define CONTENT_COMMON_RESOURCE_REQUEST_COMPLETION_STATUS_H_ +#ifndef CONTENT_PUBLIC_COMMON_RESOURCE_REQUEST_COMPLETION_STATUS_H_ +#define CONTENT_PUBLIC_COMMON_RESOURCE_REQUEST_COMPLETION_STATUS_H_ #include <stdint.h> #include <string> @@ -46,4 +46,4 @@ } // namespace content -#endif // CONTENT_COMMON_RESOURCE_REQUEST_COMPLETION_STATUS_H_ +#endif // CONTENT_PUBLIC_COMMON_RESOURCE_REQUEST_COMPLETION_STATUS_H_
diff --git a/content/public/common/service_worker_modes.typemap b/content/public/common/service_worker_modes.typemap new file mode 100644 index 0000000..bf6d5651 --- /dev/null +++ b/content/public/common/service_worker_modes.typemap
@@ -0,0 +1,11 @@ +# 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. + +mojom = "//content/public/common/service_worker_modes.mojom" +public_headers = [ "//content/public/common/service_worker_modes.h" ] +type_mappings = [ + "blink.mojom.FetchCredentialsMode=::content::FetchCredentialsMode", + "blink.mojom.FetchRedirectMode=::content::FetchRedirectMode", + "blink.mojom.FetchRequestMode=::content::FetchRequestMode", +]
diff --git a/content/common/ssl_info.typemap b/content/public/common/ssl_info.typemap similarity index 87% rename from content/common/ssl_info.typemap rename to content/public/common/ssl_info.typemap index 6e4ee34..e598fc72 100644 --- a/content/common/ssl_info.typemap +++ b/content/public/common/ssl_info.typemap
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//content/common/url_loader.mojom" +mojom = "//content/public/common/url_loader.mojom" public_headers = [ "//net/ssl/ssl_info.h" ] traits_headers = [ "//content/common/resource_messages.h" ] deps = [
diff --git a/content/public/common/typemaps.gni b/content/public/common/typemaps.gni index 2f87ff66..a9cff966 100644 --- a/content/public/common/typemaps.gni +++ b/content/public/common/typemaps.gni
@@ -4,6 +4,13 @@ typemaps = [ "//content/public/common/manifest.typemap", + "//content/public/common/mutable_network_traffic_annotation_tag.typemap", "//content/public/common/referrer.typemap", "//content/public/common/resource_type.typemap", + "//content/public/common/ssl_info.typemap", + "//content/public/common/url_loader_status.typemap", + "//content/public/common/url_request.typemap", + "//content/public/common/url_request_redirect_info.typemap", + "//content/public/common/url_response_head.typemap", + "//content/public/common/url_sync_load_result.typemap", ]
diff --git a/content/common/url_loader.mojom b/content/public/common/url_loader.mojom similarity index 100% rename from content/common/url_loader.mojom rename to content/public/common/url_loader.mojom
diff --git a/content/common/url_loader_factory.mojom b/content/public/common/url_loader_factory.mojom similarity index 100% rename from content/common/url_loader_factory.mojom rename to content/public/common/url_loader_factory.mojom
diff --git a/content/common/url_loader_status.typemap b/content/public/common/url_loader_status.typemap similarity index 74% rename from content/common/url_loader_status.typemap rename to content/public/common/url_loader_status.typemap index 66e57b63..28c8bd7e 100644 --- a/content/common/url_loader_status.typemap +++ b/content/public/common/url_loader_status.typemap
@@ -2,8 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//content/common/url_loader.mojom" -public_headers = [ "//content/common/resource_request_completion_status.h" ] +mojom = "//content/public/common/url_loader.mojom" +public_headers = + [ "//content/public/common/resource_request_completion_status.h" ] traits_headers = [ "//content/common/resource_messages.h" ] deps = [ "//content:export",
diff --git a/content/common/url_request.typemap b/content/public/common/url_request.typemap similarity index 91% rename from content/common/url_request.typemap rename to content/public/common/url_request.typemap index 6a727e1..d910b2a 100644 --- a/content/common/url_request.typemap +++ b/content/public/common/url_request.typemap
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//content/common/url_loader.mojom" +mojom = "//content/public/common/url_loader.mojom" public_headers = [ "//content/public/common/resource_request.h" ] traits_headers = [ "//content/common/resource_messages.h",
diff --git a/content/common/url_request_redirect_info.typemap b/content/public/common/url_request_redirect_info.typemap similarity index 88% rename from content/common/url_request_redirect_info.typemap rename to content/public/common/url_request_redirect_info.typemap index fcec85b..cf98da5b 100644 --- a/content/common/url_request_redirect_info.typemap +++ b/content/public/common/url_request_redirect_info.typemap
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//content/common/url_loader.mojom" +mojom = "//content/public/common/url_loader.mojom" public_headers = [ "//net/url_request/redirect_info.h" ] traits_headers = [ "//content/common/resource_messages.h" ] deps = [
diff --git a/content/common/url_response_head.typemap b/content/public/common/url_response_head.typemap similarity index 89% rename from content/common/url_response_head.typemap rename to content/public/common/url_response_head.typemap index 2918562..e67bc9c4 100644 --- a/content/common/url_response_head.typemap +++ b/content/public/common/url_response_head.typemap
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//content/common/url_loader.mojom" +mojom = "//content/public/common/url_loader.mojom" public_headers = [ "//content/public/common/resource_response.h" ] traits_headers = [ "//content/common/resource_messages.h" ] deps = [
diff --git a/content/common/url_sync_load_result.typemap b/content/public/common/url_sync_load_result.typemap similarity index 85% rename from content/common/url_sync_load_result.typemap rename to content/public/common/url_sync_load_result.typemap index a8d96175..4fd35f5 100644 --- a/content/common/url_sync_load_result.typemap +++ b/content/public/common/url_sync_load_result.typemap
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//content/common/url_loader_factory.mojom" +mojom = "//content/public/common/url_loader_factory.mojom" public_headers = [ "//content/public/common/resource_response.h" ] traits_headers = [ "//content/common/resource_messages.h" ] type_mappings = [ "content.mojom.URLSyncLoadResult=content::SyncLoadResult" ]
diff --git a/content/renderer/media/media_stream_video_capturer_source.cc b/content/renderer/media/media_stream_video_capturer_source.cc index f4d0568..583eba3 100644 --- a/content/renderer/media/media_stream_video_capturer_source.cc +++ b/content/renderer/media/media_stream_video_capturer_source.cc
@@ -197,21 +197,7 @@ device_info().session_id, device_info().device.type, is_secure)); } -void MediaStreamVideoCapturerSource::GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) { - source_->GetCurrentSupportedFormats( - max_requested_width, - max_requested_height, - max_requested_frame_rate, - callback); -} - void MediaStreamVideoCapturerSource::StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) { is_capture_starting_ = true; source_->StartCapture( @@ -225,7 +211,7 @@ } base::Optional<media::VideoCaptureFormat> -MediaStreamVideoCapturerSource::GetCurrentFormatImpl() const { +MediaStreamVideoCapturerSource::GetCurrentFormat() const { return base::Optional<media::VideoCaptureFormat>( capture_params_.requested_format); }
diff --git a/content/renderer/media/media_stream_video_capturer_source.h b/content/renderer/media/media_stream_video_capturer_source.h index ee8abe2..f4fa6067 100644 --- a/content/renderer/media/media_stream_video_capturer_source.h +++ b/content/renderer/media/media_stream_video_capturer_source.h
@@ -48,18 +48,10 @@ void RequestRefreshFrame() override; void OnHasConsumers(bool has_consumers) override; void OnCapturingLinkSecured(bool is_secure) override; - void GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) override; void StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) override; void StopSourceImpl() override; - base::Optional<media::VideoCaptureFormat> GetCurrentFormatImpl() - const override; + base::Optional<media::VideoCaptureFormat> GetCurrentFormat() const override; // RenderFrameObserver implementation. void OnDestruct() final {}
diff --git a/content/renderer/media/media_stream_video_capturer_source_unittest.cc b/content/renderer/media/media_stream_video_capturer_source_unittest.cc index 11efe04..0735060 100644 --- a/content/renderer/media/media_stream_video_capturer_source_unittest.cc +++ b/content/renderer/media/media_stream_video_capturer_source_unittest.cc
@@ -33,35 +33,15 @@ class MockVideoCapturerSource : public media::VideoCapturerSource { public: - MockVideoCapturerSource() { - ON_CALL(*this, GetCurrentSupportedFormats(_, _, _, _)) - .WillByDefault(WithArgs<3>( - Invoke(this, &MockVideoCapturerSource::EnumerateDeviceFormats))); - } + MockVideoCapturerSource() {} MOCK_METHOD0(RequestRefreshFrame, void()); - MOCK_METHOD4(GetCurrentSupportedFormats, - void(int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback)); MOCK_METHOD0(GetPreferredFormats, media::VideoCaptureFormats()); MOCK_METHOD3(StartCapture, void(const media::VideoCaptureParams& params, const VideoCaptureDeliverFrameCB& new_frame_callback, const RunningCallback& running_callback)); MOCK_METHOD0(StopCapture, void()); - - void EnumerateDeviceFormats(const VideoCaptureDeviceFormatsCB& callback) { - media::VideoCaptureFormat kFormatSmall(gfx::Size(640, 480), 30.0, - media::PIXEL_FORMAT_I420); - media::VideoCaptureFormat kFormatLarge(gfx::Size(1920, 1080), 30.0, - media::PIXEL_FORMAT_I420); - media::VideoCaptureFormats formats; - formats.push_back(kFormatSmall); - formats.push_back(kFormatLarge); - callback.Run(formats); - } }; class FakeMediaStreamVideoSink : public MediaStreamVideoSink {
diff --git a/content/renderer/media/media_stream_video_renderer_sink_unittest.cc b/content/renderer/media/media_stream_video_renderer_sink_unittest.cc index 6ced490..b65d93b 100644 --- a/content/renderer/media/media_stream_video_renderer_sink_unittest.cc +++ b/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
@@ -40,7 +40,7 @@ public: MediaStreamVideoRendererSinkTest() : child_process_(new ChildProcess()), - mock_source_(new MockMediaStreamVideoSource(false)) { + mock_source_(new MockMediaStreamVideoSource()) { blink_source_.Initialize(blink::WebString::FromASCII("dummy_source_id"), blink::WebMediaStreamSource::kTypeVideo, blink::WebString::FromASCII("dummy_source_name"),
diff --git a/content/renderer/media/media_stream_video_source.cc b/content/renderer/media/media_stream_video_source.cc index 54852968b..203d632 100644 --- a/content/renderer/media/media_stream_video_source.cc +++ b/content/renderer/media/media_stream_video_source.cc
@@ -61,9 +61,7 @@ switch (state_) { case NEW: { state_ = STARTING; - blink::WebMediaConstraints ignored_constraints; StartSourceImpl( - media::VideoCaptureFormat() /* ignored */, ignored_constraints, base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_)); break; } @@ -132,11 +130,6 @@ base::Optional<media::VideoCaptureFormat> MediaStreamVideoSource::GetCurrentFormat() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return GetCurrentFormatImpl(); -} - -base::Optional<media::VideoCaptureFormat> -MediaStreamVideoSource::GetCurrentFormatImpl() const { return base::Optional<media::VideoCaptureFormat>(); }
diff --git a/content/renderer/media/media_stream_video_source.h b/content/renderer/media/media_stream_video_source.h index c5f03c63..9fdc291 100644 --- a/content/renderer/media/media_stream_video_source.h +++ b/content/renderer/media/media_stream_video_source.h
@@ -37,13 +37,6 @@ // MediaStreaVideoSources such as local video capture, video sources received // on a PeerConnection or a source created in NaCl. // All methods calls will be done from the main render thread. -// -// When the first track is added to the source by calling AddTrack, the -// MediaStreamVideoSource implementation calls GetCurrentSupportedFormats. -// The source implementation must call OnSupportedFormats. -// MediaStreamVideoSource then match the constraints provided in AddTrack with -// the formats and call StartSourceImpl. The source implementation must call -// OnStartDone when the underlying source has been started or failed to start. class CONTENT_EXPORT MediaStreamVideoSource : public MediaStreamSource { public: enum { @@ -85,7 +78,8 @@ // Returns the task runner where video frames will be delivered on. base::SingleThreadTaskRunner* io_task_runner() const; - base::Optional<media::VideoCaptureFormat> GetCurrentFormat() const; + // Implementations must return the capture format if available. + virtual base::Optional<media::VideoCaptureFormat> GetCurrentFormat() const; base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() { return weak_factory_.GetWeakPtr(); @@ -100,35 +94,11 @@ // Sets muted state and notifies it to all registered tracks. virtual void SetMutedState(bool state); - // An implementation must fetch the formats that can currently be used by - // the source and call OnSupportedFormats when done. - // |max_requested_height| and |max_requested_width| is the max height and - // width set as a mandatory constraint if set when calling - // MediaStreamVideoSource::AddTrack. If max height and max width is not set - // |max_requested_height| and |max_requested_width| are 0. - // TODO(guidou): Remove when the standard constraints code stabilizes. - // http://crbug.com/706408 - virtual void GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) = 0; - - // TODO(guidou): Rename to GetCurrentFormat. http://crbug.com/706804 - virtual base::Optional<media::VideoCaptureFormat> GetCurrentFormatImpl() - const; - - // An implementation must start capturing frames using the requested - // |format|. The fulfilled |constraints| are provided as additional context, - // and may be used to modify the behavior of the source. When the source has - // started or the source failed to start OnStartDone must be called. An - // implementation must call |frame_callback| on the IO thread with the + // An implementation must start capturing frames after this method is called. + // When the source has started or failed to start OnStartDone must be called. + // An implementation must call |frame_callback| on the IO thread with the // captured frames. - // TODO(guidou): Remove |format| and |constraints| parameters. - // http://crbug.com/706408 virtual void StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) = 0; void OnStartDone(MediaStreamRequestResult result);
diff --git a/content/renderer/media/mock_media_stream_registry.cc b/content/renderer/media/mock_media_stream_registry.cc index 7f10526e..ff5ecdf 100644 --- a/content/renderer/media/mock_media_stream_registry.cc +++ b/content/renderer/media/mock_media_stream_registry.cc
@@ -66,8 +66,7 @@ blink_source.Initialize("mock video source id", blink::WebMediaStreamSource::kTypeVideo, "mock video source name", false /* remote */); - MockMediaStreamVideoSource* native_source = - new MockMediaStreamVideoSource(false /* manual get supported formats */); + MockMediaStreamVideoSource* native_source = new MockMediaStreamVideoSource(); blink_source.SetExtraData(native_source); blink::WebMediaStreamTrack blink_track; blink_track.Initialize(blink::WebString::FromUTF8(track_id), blink_source);
diff --git a/content/renderer/media/mock_media_stream_video_source.cc b/content/renderer/media/mock_media_stream_video_source.cc index 05070df..d134d46 100644 --- a/content/renderer/media/mock_media_stream_video_source.cc +++ b/content/renderer/media/mock_media_stream_video_source.cc
@@ -10,30 +10,21 @@ namespace content { -MockMediaStreamVideoSource::MockMediaStreamVideoSource( - bool manual_get_supported_formats) - : MockMediaStreamVideoSource(manual_get_supported_formats, false) {} +MockMediaStreamVideoSource::MockMediaStreamVideoSource() + : MockMediaStreamVideoSource(false) {} MockMediaStreamVideoSource::MockMediaStreamVideoSource( - bool manual_get_supported_formats, bool respond_to_request_refresh_frame) - : manual_get_supported_formats_(manual_get_supported_formats), - respond_to_request_refresh_frame_(respond_to_request_refresh_frame), + : respond_to_request_refresh_frame_(respond_to_request_refresh_frame), max_requested_height_(0), max_requested_width_(0), max_requested_frame_rate_(0.0), - attempted_to_start_(false) { - supported_formats_.push_back(media::VideoCaptureFormat( - gfx::Size(MediaStreamVideoSource::kDefaultWidth, - MediaStreamVideoSource::kDefaultHeight), - MediaStreamVideoSource::kDefaultFrameRate, media::PIXEL_FORMAT_I420)); -} + attempted_to_start_(false) {} MockMediaStreamVideoSource::MockMediaStreamVideoSource( const media::VideoCaptureFormat& format, bool respond_to_request_refresh_frame) : format_(format), - manual_get_supported_formats_(false), respond_to_request_refresh_frame_(respond_to_request_refresh_frame), max_requested_height_(format.frame_size.height()), max_requested_width_(format.frame_size.width()), @@ -54,11 +45,6 @@ OnStartDone(MEDIA_DEVICE_TRACK_START_FAILURE); } -void MockMediaStreamVideoSource::CompleteGetSupportedFormats() { - DCHECK(!formats_callback_.is_null()); - base::ResetAndReturn(&formats_callback_).Run(supported_formats_); -} - void MockMediaStreamVideoSource::RequestRefreshFrame() { DCHECK(!frame_callback_.is_null()); if (respond_to_request_refresh_frame_) { @@ -70,26 +56,7 @@ } } -void MockMediaStreamVideoSource::GetCurrentSupportedFormats( - int max_requested_height, - int max_requested_width, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) { - DCHECK(formats_callback_.is_null()); - max_requested_height_ = max_requested_height; - max_requested_width_ = max_requested_width; - max_requested_frame_rate_ = max_requested_frame_rate; - - if (manual_get_supported_formats_) { - formats_callback_ = callback; - return; - } - callback.Run(supported_formats_); -} - void MockMediaStreamVideoSource::StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) { DCHECK(frame_callback_.is_null()); attempted_to_start_ = true; @@ -100,7 +67,8 @@ } base::Optional<media::VideoCaptureFormat> -MockMediaStreamVideoSource::GetCurrentFormatImpl() const { +MockMediaStreamVideoSource::GetCurrentFormat() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return base::Optional<media::VideoCaptureFormat>(format_); }
diff --git a/content/renderer/media/mock_media_stream_video_source.h b/content/renderer/media/mock_media_stream_video_source.h index 7c4746e..0dac396 100644 --- a/content/renderer/media/mock_media_stream_video_source.h +++ b/content/renderer/media/mock_media_stream_video_source.h
@@ -14,9 +14,8 @@ class MockMediaStreamVideoSource : public MediaStreamVideoSource { public: - explicit MockMediaStreamVideoSource(bool manual_get_supported_formats); - MockMediaStreamVideoSource(bool manual_get_supported_formats, - bool respond_to_request_refresh_frame); + MockMediaStreamVideoSource(); + explicit MockMediaStreamVideoSource(bool respond_to_request_refresh_frame); MockMediaStreamVideoSource(const media::VideoCaptureFormat& format, bool respond_to_request_refresh_frame); virtual ~MockMediaStreamVideoSource(); @@ -33,10 +32,6 @@ // or FailToStartMockedSource has not been called. bool SourceHasAttemptedToStart() { return attempted_to_start_; } - void SetSupportedFormats(const media::VideoCaptureFormats& formats) { - supported_formats_ = formats; - } - // Delivers |frame| to all registered tracks on the IO thread. Its up to the // call to make sure MockMediaStreamVideoSource is not destroyed before the // frame has been delivered. @@ -59,29 +54,18 @@ protected: // Implements MediaStreamVideoSource. - void GetCurrentSupportedFormats( - int max_requested_height, - int max_requested_width, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) override; void StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) override; void StopSourceImpl() override; - base::Optional<media::VideoCaptureFormat> GetCurrentFormatImpl() - const override; + base::Optional<media::VideoCaptureFormat> GetCurrentFormat() const override; private: media::VideoCaptureFormat format_; - media::VideoCaptureFormats supported_formats_; - bool manual_get_supported_formats_; bool respond_to_request_refresh_frame_; int max_requested_height_; int max_requested_width_; double max_requested_frame_rate_; bool attempted_to_start_; - VideoCaptureDeviceFormatsCB formats_callback_; VideoCaptureDeliverFrameCB frame_callback_; DISALLOW_COPY_AND_ASSIGN(MockMediaStreamVideoSource);
diff --git a/content/renderer/media/pepper_to_video_track_adapter.cc b/content/renderer/media/pepper_to_video_track_adapter.cc index 104bd01..ca3b2db 100644 --- a/content/renderer/media/pepper_to_video_track_adapter.cc +++ b/content/renderer/media/pepper_to_video_track_adapter.cc
@@ -46,14 +46,7 @@ protected: // MediaStreamVideoSource implementation. - void GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) override; void StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) override; void StopSourceImpl() override; @@ -116,22 +109,7 @@ DVLOG(3) << "PpFrameWriter dtor"; } -void PpFrameWriter::GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()"; - // Since the input is free to change the resolution at any point in time - // the supported formats are unknown. - media::VideoCaptureFormats formats; - callback.Run(formats); -} - void PpFrameWriter::StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!delegate_.get());
diff --git a/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/rtc_peer_connection_handler_unittest.cc index 66d6be9..91cb0f5 100644 --- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc +++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -313,7 +313,7 @@ blink::WebString::FromUTF8("video_track"), false /* remote */); MockMediaStreamVideoSource* native_video_source = - new MockMediaStreamVideoSource(false); + new MockMediaStreamVideoSource(); video_source.SetExtraData(native_video_source); blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
diff --git a/content/renderer/media/user_media_client_impl_unittest.cc b/content/renderer/media/user_media_client_impl_unittest.cc index b5505f0..0230fdb 100644 --- a/content/renderer/media/user_media_client_impl_unittest.cc +++ b/content/renderer/media/user_media_client_impl_unittest.cc
@@ -98,11 +98,10 @@ class MockMediaStreamVideoCapturerSource : public MockMediaStreamVideoSource { public: - MockMediaStreamVideoCapturerSource( - const StreamDeviceInfo& device, - const SourceStoppedCallback& stop_callback, - PeerConnectionDependencyFactory* factory) - : MockMediaStreamVideoSource(false) { + MockMediaStreamVideoCapturerSource(const StreamDeviceInfo& device, + const SourceStoppedCallback& stop_callback, + PeerConnectionDependencyFactory* factory) + : MockMediaStreamVideoSource() { SetDeviceInfo(device); SetStopCallback(stop_callback); }
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/content/renderer/media/webrtc/media_stream_remote_video_source.cc index bf34d04..bfadcb9f 100644 --- a/content/renderer/media/webrtc/media_stream_remote_video_source.cc +++ b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -186,21 +186,7 @@ StopSourceImpl(); } -void MediaStreamRemoteVideoSource::GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - media::VideoCaptureFormats formats; - // Since the remote end is free to change the resolution at any point in time - // the supported formats are unknown. - callback.Run(formats); -} - void MediaStreamRemoteVideoSource::StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!delegate_.get());
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.h b/content/renderer/media/webrtc/media_stream_remote_video_source.h index b3d50cd..0355ae8 100644 --- a/content/renderer/media/webrtc/media_stream_remote_video_source.h +++ b/content/renderer/media/webrtc/media_stream_remote_video_source.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_REMOTE_VIDEO_SOURCE_H_ #define CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_REMOTE_VIDEO_SOURCE_H_ +#include <memory> + #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -24,7 +26,8 @@ class CONTENT_EXPORT MediaStreamRemoteVideoSource : public MediaStreamVideoSource { public: - MediaStreamRemoteVideoSource(std::unique_ptr<TrackObserver> observer); + explicit MediaStreamRemoteVideoSource( + std::unique_ptr<TrackObserver> observer); ~MediaStreamRemoteVideoSource() override; // Should be called when the remote video track this source originates from is @@ -34,15 +37,7 @@ protected: // Implements MediaStreamVideoSource. - void GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) override; - void StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) override; void StopSourceImpl() override;
diff --git a/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc b/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc index db43fcdd..4ecec10 100644 --- a/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc +++ b/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc
@@ -5,6 +5,7 @@ #include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include <memory> +#include <string> #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop.h" @@ -50,8 +51,7 @@ video_source.Initialize("video_source", blink::WebMediaStreamSource::kTypeVideo, "video_source", false /* remote */); - MediaStreamVideoSource* native_source = - new MockMediaStreamVideoSource(false); + MediaStreamVideoSource* native_source = new MockMediaStreamVideoSource(); video_source.SetExtraData(native_source); web_video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack( native_source, MediaStreamVideoSource::ConstraintsCallback(), true);
diff --git a/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc index 1d4204eb..6c26895c3 100644 --- a/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc +++ b/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
@@ -83,8 +83,7 @@ blink::WebMediaStreamSource video_source; video_source.Initialize("video", blink::WebMediaStreamSource::kTypeVideo, "video", false /* remote */); - MediaStreamVideoSource* native_source = - new MockMediaStreamVideoSource(false); + MediaStreamVideoSource* native_source = new MockMediaStreamVideoSource(); video_source.SetExtraData(native_source); video_track_vector[0] = MediaStreamVideoTrack::CreateVideoTrack( native_source, MediaStreamVideoSource::ConstraintsCallback(), true);
diff --git a/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc index 2a14cc4..247b3096 100644 --- a/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc +++ b/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc
@@ -65,8 +65,7 @@ blink::WebMediaStreamSource::kTypeVideo, blink::WebString::FromUTF8("local_video_track"), false); - MockMediaStreamVideoSource* video_source = - new MockMediaStreamVideoSource(true); + MockMediaStreamVideoSource* video_source = new MockMediaStreamVideoSource(); // Takes ownership of |video_source|. web_source.SetExtraData(video_source);
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc b/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc index 76a214b..c3af903 100644 --- a/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc +++ b/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc
@@ -74,12 +74,6 @@ DoOnDeliverFrame(video_frame, estimated_capture_time); } - MOCK_METHOD1(DoOnVideoCaptureDeviceFormats, - void(const media::VideoCaptureFormats&)); - void OnVideoCaptureDeviceFormats(const media::VideoCaptureFormats& formats) { - DoOnVideoCaptureDeviceFormats(formats); - } - MOCK_METHOD1(DoOnRunning, void(bool)); void OnRunning(bool state) { DoOnRunning(state); } @@ -174,16 +168,7 @@ media::VideoCapturerSource* source = GetVideoCapturerSource(ms_source); EXPECT_TRUE(source != nullptr); - media::VideoCaptureFormats formats; - EXPECT_CALL(*this, DoOnVideoCaptureDeviceFormats(_)) - .Times(1) - .WillOnce(SaveArg<0>(&formats)); - source->GetCurrentSupportedFormats( - media::limits::kMaxCanvas /* max_requesteed_width */, - media::limits::kMaxCanvas /* max_requesteed_height */, - media::limits::kMaxFramesPerSecond /* max_requested_frame_rate */, - base::Bind(&CanvasCaptureHandlerTest::OnVideoCaptureDeviceFormats, - base::Unretained(this))); + media::VideoCaptureFormats formats = source->GetPreferredFormats(); ASSERT_EQ(2u, formats.size()); EXPECT_EQ(kTestCanvasCaptureWidth, formats[0].frame_size.width()); EXPECT_EQ(kTestCanvasCaptureHeight, formats[0].frame_size.height());
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc index 8f2ffa07..95e73fd 100644 --- a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc +++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -99,12 +99,6 @@ DoOnDeliverFrame(video_frame, estimated_capture_time); } - MOCK_METHOD1(DoOnVideoCaptureDeviceFormats, - void(const media::VideoCaptureFormats&)); - void OnVideoCaptureDeviceFormats(const media::VideoCaptureFormats& formats) { - DoOnVideoCaptureDeviceFormats(formats); - } - MOCK_METHOD1(DoOnRunning, void(bool)); void OnRunning(bool state) { DoOnRunning(state); } @@ -126,18 +120,8 @@ // frames. TEST_F(HTMLVideoElementCapturerSourceTest, GetFormatsAndStartAndStop) { InSequence s; - media::VideoCaptureFormats formats; - EXPECT_CALL(*this, DoOnVideoCaptureDeviceFormats(_)) - .Times(1) - .WillOnce(SaveArg<0>(&formats)); - - html_video_capturer_->GetCurrentSupportedFormats( - media::limits::kMaxCanvas /* max_requesteed_width */, - media::limits::kMaxCanvas /* max_requesteed_height */, - media::limits::kMaxFramesPerSecond /* max_requested_frame_rate */, - base::Bind( - &HTMLVideoElementCapturerSourceTest::OnVideoCaptureDeviceFormats, - base::Unretained(this))); + media::VideoCaptureFormats formats = + html_video_capturer_->GetPreferredFormats(); ASSERT_EQ(1u, formats.size()); EXPECT_EQ(web_media_player_->NaturalSize().width, formats[0].frame_size.width());
diff --git a/content/renderer/media_recorder/video_track_recorder_unittest.cc b/content/renderer/media_recorder/video_track_recorder_unittest.cc index 287127c..572c216 100644 --- a/content/renderer/media_recorder/video_track_recorder_unittest.cc +++ b/content/renderer/media_recorder/video_track_recorder_unittest.cc
@@ -61,8 +61,7 @@ : public TestWithParam< testing::tuple<VideoTrackRecorder::CodecId, gfx::Size, bool>> { public: - VideoTrackRecorderTest() - : mock_source_(new MockMediaStreamVideoSource(false)) { + VideoTrackRecorderTest() : mock_source_(new MockMediaStreamVideoSource()) { const blink::WebString webkit_track_id( blink::WebString::FromASCII("dummy")); blink_source_.Initialize(webkit_track_id,
diff --git a/content/renderer/pepper/pepper_media_stream_video_track_host.cc b/content/renderer/pepper/pepper_media_stream_video_track_host.cc index 4924a98..b486a17 100644 --- a/content/renderer/pepper/pepper_media_stream_video_track_host.cc +++ b/content/renderer/pepper/pepper_media_stream_video_track_host.cc
@@ -414,23 +414,7 @@ ~VideoSource() final { StopSourceImpl(); } - void GetCurrentSupportedFormats( - int max_requested_width, int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) final { - media::VideoCaptureFormats formats; - if (host_) { - formats.push_back(media::VideoCaptureFormat( - host_->plugin_frame_size_, - kDefaultOutputFrameRate, - ToPixelFormat(host_->plugin_frame_format_))); - } - callback.Run(formats); - } - void StartSourceImpl( - const media::VideoCaptureFormat& format, - const blink::WebMediaConstraints& constraints, const VideoCaptureDeliverFrameCB& frame_callback) final { if (host_) { host_->frame_deliverer_ = @@ -444,8 +428,7 @@ } private: - base::Optional<media::VideoCaptureFormat> GetCurrentFormatImpl() - const override { + base::Optional<media::VideoCaptureFormat> GetCurrentFormat() const override { if (host_) { return base::Optional<media::VideoCaptureFormat>( media::VideoCaptureFormat(
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 71fd95c..7683fb5 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -37,7 +37,6 @@ #include "content/common/host_zoom.mojom.h" #include "content/common/renderer.mojom.h" #include "content/common/unique_name_helper.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/common/console_message_level.h" #include "content/public/common/javascript_dialog_type.h" #include "content/public/common/previews_state.h" @@ -45,6 +44,7 @@ #include "content/public/common/renderer_preferences.h" #include "content/public/common/request_context_type.h" #include "content/public/common/stop_find_action.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "content/public/renderer/render_frame.h" #include "content/renderer/frame_blame_context.h" #include "content/renderer/media/media_factory.h"
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 8cf0aef8..6ae346c 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -2517,11 +2517,13 @@ v8::MemoryPressureLevel v8_memory_pressure_level = static_cast<v8::MemoryPressureLevel>(memory_pressure_level); +#if !BUILDFLAG(ALLOW_CRITICAL_MEMORY_PRESSURE_HANDLING_IN_FOREGROUND) // In order to reduce performance impact, translate critical level to - // moderate level for foregroud renderer. + // moderate level for foreground renderer. if (!RendererIsHidden() && v8_memory_pressure_level == v8::MemoryPressureLevel::kCritical) v8_memory_pressure_level = v8::MemoryPressureLevel::kModerate; +#endif // !BUILDFLAG(ALLOW_CRITICAL_MEMORY_PRESSURE_HANDLING_IN_FOREGROUND) blink::MainThreadIsolate()->MemoryPressureNotification( v8_memory_pressure_level);
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index a05e2740..e653a59 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -42,7 +42,7 @@ #include "content/common/renderer.mojom.h" #include "content/common/renderer_host.mojom.h" #include "content/common/storage_partition_service.mojom.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/gpu/compositor_dependencies.h" #include "content/renderer/layout_test_dependencies.h"
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index 3ea9374..c5614a1 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -20,7 +20,7 @@ #include "content/child/blink_platform_impl.h" #include "content/common/content_export.h" #include "content/common/possibly_associated_interface_ptr.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "content/renderer/origin_trials/web_trial_token_validator_impl.h" #include "content/renderer/top_level_blame_context.h" #include "content/renderer/webpublicsuffixlist_impl.h"
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 785bd7a..8003b96 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -231,7 +231,7 @@ "//content/app/resources", "//content/app/strings", "//content/gpu", - "//content/public/common:interfaces", + "//content/public/common", "//content/public/common:service_names", "//content/shell/test_runner:test_runner", "//content/test:content_test_mojo_bindings",
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index c44a09e..0a63b0d 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -262,7 +262,7 @@ "//content/gpu", "//content/public/browser", "//content/public/child", - "//content/public/common:interfaces", + "//content/public/common", "//content/public/common:service_names", "//content/public/renderer", "//content/public/utility", @@ -350,9 +350,9 @@ deps += [ "//third_party/webrtc/api:libjingle_peerconnection", "//third_party/webrtc/api:rtc_stats_api", - "//third_party/webrtc/rtc_base:rtc_base_approved", "//third_party/webrtc/media:rtc_media_base", "//third_party/webrtc/modules/video_capture", + "//third_party/webrtc/rtc_base:rtc_base_approved", "//third_party/webrtc/stats:rtc_stats", "//third_party/webrtc_overrides:init_webrtc", ] @@ -1699,10 +1699,10 @@ "//third_party/webrtc/api:rtc_stats_api", "//third_party/webrtc/api:video_frame_api", "//third_party/webrtc/api/video_codecs:video_codecs_api", - "//third_party/webrtc/rtc_base:rtc_base", "//third_party/webrtc/media:rtc_media", "//third_party/webrtc/modules/desktop_capture:primitives", "//third_party/webrtc/modules/video_capture", + "//third_party/webrtc/rtc_base:rtc_base", "//third_party/webrtc/stats:rtc_stats_test_utils", "//third_party/webrtc_overrides:init_webrtc", "//ui/shell_dialogs:shell_dialogs",
diff --git a/content/test/test_navigation_url_loader.cc b/content/test/test_navigation_url_loader.cc index 7ea49f2..6a7477d 100644 --- a/content/test/test_navigation_url_loader.cc +++ b/content/test/test_navigation_url_loader.cc
@@ -7,7 +7,6 @@ #include <utility> #include "content/browser/loader/navigation_url_loader_delegate.h" -#include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/navigation_data.h" #include "content/public/browser/render_process_host.h" @@ -16,6 +15,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/browser_side_navigation_policy.h" #include "content/public/common/resource_response.h" +#include "content/public/common/url_loader_factory.mojom.h" #include "net/url_request/redirect_info.h" namespace content {
diff --git a/docs/README.md b/docs/README.md index b4601df..d9f77bd 100644 --- a/docs/README.md +++ b/docs/README.md
@@ -294,6 +294,8 @@ used to automatically set proxy settings. * [Installing Chromium OS on VMWare](installation_at_vmware.md) - How to install Chromium OS on VMWare. +* [User Data Directory](user_data_dir.md) - How the user data and cache + directories are determined on all platforms. ### Probably Obsolete * [Old ChromeOS build instructions](old_chromeos_build_instructions.md)
diff --git a/docs/user_data_dir.md b/docs/user_data_dir.md new file mode 100644 index 0000000..64643d1 --- /dev/null +++ b/docs/user_data_dir.md
@@ -0,0 +1,219 @@ +# User Data Directory + +[TOC] + +## Introduction + +The user data directory contains profile data such as history, bookmarks, and +cookies, as well as other per-installation local state. + +Each [profile](https://support.google.com/chrome/answer/2364824) is a +subdirectory (often `Default`) within the user data directory. + +## Current Location + +To determine the user data directory for a running Chrome instance: + +1. Navigate to `chrome://version` +2. Look for the `Profile Path` field. This gives the path to the profile + directory. +3. The user data directory is the parent of the profile directory. + +Example (Windows): + +* [Profile Path] `C:\Users\Alice\AppData\Local\Google\Chrome\User Data\Default` +* [User Data Dir] `C:\Users\Alice\AppData\Local\Google\Chrome\User Data` + +## Default Location + +The default location of the user data directory is computed by +[`chrome::GetDefaultUserDataDirectory`](https://cs.chromium.org/chromium/src/chrome/common/chrome_paths_internal.h?q=GetDefaultUserDataDirectory). + +Generally it varies by + +* OS platform, +* branding ([Chrome vs. Chromium](chromium_browser_vs_google_chrome.md), based + on `is_chrome_branded` in [GN + args](https://www.chromium.org/developers/gn-build-configuration)), and +* [release channel](https://www.chromium.org/getting-involved/dev-channel) + (stable / beta / dev / canary). + +### Windows + +The default location is in the local app data folder: + +* [Chrome] `%LOCALAPPDATA%\Google\Chrome\User Data` +* [Chrome Canary] `%LOCALAPPDATA%\Google\Chrome SxS\User Data` +* [Chromium] `%LOCALAPPDATA%\Chromium\User Data` + +(The canary channel suffix is determined using +[`InstallConstants::install_suffix`](https://cs.chromium.org/chromium/src/chrome/install_static/install_constants.h?q=install_suffix).) + +### Mac OS X + +The default location is in the `Application Support` folder: + +* [Chrome] `~/Library/Application Support/Google/Chrome` +* [Chrome Canary] `~/Library/Application Support/Google/Chrome Canary` +* [Chromium] `~/Library/Application Support/Chromium` + +(The canary channel suffix is determined using the `CrProductDirName` key in the +browser app's `Info.plist`.) + +### Linux + +The default location is in `~/.config`: + +* [Chrome Stable] `~/.config/google-chrome` +* [Chrome Beta] `~/.config/google-chrome-beta` +* [Chrome Dev] `~/.config/google-chrome-unstable` +* [Chromium] `~/.config/chromium` + +(The beta and dev channel suffixes are determined from `$CHROME_VERSION_EXTRA`, +which is passed by the [launch wrapper script](https://cs.chromium.org/chromium/src/chrome/installer/linux/common/wrapper?q=CHROME_VERSION_EXTRA).) + +The `~/.config` portion of the default location can be overridden by +`$CHROME_CONFIG_HOME` (since M61) or by `$XDG_CONFIG_HOME`. + +Note that `$XDG_CONFIG_HOME` affects all applications conforming to the +[XDG Base Directory Spec](https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html), +while `$CHROME_CONFIG_HOME` is specific to Chrome and Chromium. + +### Chrome OS + +The default location is: `/home/chronos` + +### Android + +The default location comes from +[Context.getDir](https://developer.android.com/reference/android/content/Context.html#getDir(java.lang.String, int)) +and is specific to the app. + +Example: `/data/user/0/com.android.chrome/app_chrome` + +### iOS + +The default location is inside the application support directory in the app +sandbox. + +* [Chrome] `Library/Application Support/Google/Chrome` +* [Chromium] `Library/Application Support/Chromium` + +## Overriding the User Data Directory + +### Command Line + +On all platforms, the user data directory can be overridden by passing the +`--user-data-dir` command-line flag to the Chrome binary. + +Example: + +* [Windows] `chrome.exe --user-data-dir=c:\foo` +* [Linux] `google-chrome --user-data-dir=/path/to/foo` + +### Environment (Linux) + +On Linux, the user data directory can also be overridden with the +`$CHROME_USER_DATA_DIR` environment variable. + +The `--user-data-dir` flag takes precedence if both are present. + +### Chrome Remote Desktop sessions (Linux) + +A single Chrome instance cannot show windows on multiple X displays, and two +running Chrome instances cannot share the same user data directory. +Therefore, it's desirable for Chrome to have a separate user data directory +when running inside a [Chrome Remote +Desktop](https://support.google.com/chrome/answer/1649523) (CRD) virtual session +on a Linux host. + +By default, CRD achieves this by setting `$CHROME_USER_DATA_DIR` in the session. +Unfortunately this means that inside the session we don't get separate defaults +for different channels (Stable, Beta, Dev) or for Chrome vs. Chromium. This can +lead to profile version errors ("Your profile can not be used because it is from +a newer version of Google Chrome"). + +Since M61, this can be solved by setting `$CHROME_CONFIG_HOME` instead of +`$CHROME_USER_DATA_DIR`. Specifically, put the following in +`~/.chrome-remote-desktop-session`: + +``` +export CHROME_CONFIG_HOME="$HOME/.config/chrome-remote-desktop/chrome-config" +unset CHROME_USER_DATA_DIR +. /etc/chrome-remote-desktop-session +``` + +Then restart the host by running: `/etc/init.d/chrome-remote-desktop restart` + +### Writing an AppleScript wrapper (Mac OS X) + +On Mac OS X, you can create an application that runs Chrome with a custom +`--user-data-dir`: + +1. Open Applications > Utilities > Script Editor. + +2. Enter: + +``` +set chrome to "\"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\"" +set userdatadir to "\"$HOME/Library/Application Support/Google/Chrome Alt\"" +do shell script chrome & " --user-data-dir=" & userdatadir & " > /dev/null 2>&1 &" +``` + +3. Modify as needed for your installation path, Chrome versus Chromium, and + desired user data directory. + +4. Save the script in your Applications directory with the file format + "Application". + +5. Close the Script Editor, find your newly created application, and run it. + This opens a Chrome instance pointing to your new profile. + +If you want, you can give this application the same icon as Chrome: + +1. Select the Google Chrome application and choose File > Get Info. +2. Select the icon at the top left of the info dialog. You will see a blue + highlight around the icon. +3. Press ⌘C to copy the icon. +4. Open the info dialog for the new application and select the icon in the + top left. +5. Press ⌘V to paste the copied icon. + +## User Cache Directory + +On Windows and ChromeOS, the user cache dir is the same as the profile dir. +(The profile dir is inside the user data dir.) + +On Mac OS X and iOS, the user cache dir is derived from the profile dir as +follows: + +1. If `Library/Application Support` is an ancestor of the profile dir, the user + cache dir is `Library/Caches` plus the relative path from `Application + Support` to the profile dir. +2. Otherwise, the user cache dir is the same as the profile dir. + +Example (Mac OS X): + +* [user data dir] `~/Library/Application Support/Google/Chrome` +* [profile dir] `~/Library/Application Support/Google/Chrome/Default` +* [user cache dir] `~/Library/Caches/Google/Chrome/Default` + +On Linux, the user cache dir is derived from the profile dir as follows: + +1. Determine the system config dir. This is `~/.config`, unless overridden by + `$XDG_CONFIG_HOME`. (This step ignores `$CHROME_CONFIG_HOME`.) +2. Determine the system cache dir. This is `~/.cache`, unless overridden by + `$XDG_CACHE_HOME`. +3. If the system config dir is an ancestor of the profile dir, the user cache + dir is the system cache dir plus the relative path from the system config + dir to the profile dir. +4. Otherwise, the user cache dir is the same as the profile dir. + +Example (Linux): + +* [user data dir] `~/.config/google-chrome` +* [profile dir] `~/.config/google-chrome/Default` +* [user cache dir] `~/.cache/google-chrome/Default` + +On Android, the user cache directory comes from +[Context.getCacheDir](https://developer.android.com/reference/android/content/Context.html#getCacheDir()).
diff --git a/ios/build/bots/tests/common_tests.json b/ios/build/bots/tests/common_tests.json index d720305..f0e18794 100644 --- a/ios/build/bots/tests/common_tests.json +++ b/ios/build/bots/tests/common_tests.json
@@ -16,9 +16,6 @@ "app": "ios_net_unittests" }, { - "app": "ios_web_view_inttests" - }, - { "app": "net_unittests" }, {
diff --git a/ios/chrome/browser/payments/payment_request.h b/ios/chrome/browser/payments/payment_request.h index 52a58db..1abcb8d 100644 --- a/ios/chrome/browser/payments/payment_request.h +++ b/ios/chrome/browser/payments/payment_request.h
@@ -12,6 +12,7 @@ #include <vector> #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "components/autofill/core/browser/credit_card.h" #include "components/payments/core/payment_options_provider.h" #include "components/payments/core/payment_request_base_delegate.h" @@ -28,6 +29,8 @@ class AddressNormalizer; class AddressNormalizerImpl; class CurrencyFormatter; +class PaymentInstrument; +class AutofillPaymentInstrument; } // namespace payments namespace ios { @@ -39,7 +42,11 @@ // initiating UI to request full card details for payment. @protocol PaymentRequestUIDelegate<NSObject> -- (void)openFullCardRequestUI; +- (void) +requestFullCreditCard:(const autofill::CreditCard&)creditCard + resultDelegate: + (base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>) + resultDelegate; @end @@ -151,10 +158,6 @@ return supported_card_networks_; } - const std::set<std::string>& basic_card_specified_networks() const { - return basic_card_specified_networks_; - } - const std::map<std::string, std::set<std::string>>& stringified_method_data() const { return stringified_method_data_; @@ -165,27 +168,27 @@ return supported_card_types_set_; } - // Adds |credit_card| to the list of cached credit cards, updates the list of - // available credit cards, and returns a reference to the cached copy of + // Creates and adds an AutofillPaymentInstrument, which makes a copy of // |credit_card|. - virtual autofill::CreditCard* AddCreditCard( + virtual payments::AutofillPaymentInstrument* AddAutofillPaymentInstrument( const autofill::CreditCard& credit_card); - // Returns the available autofill credit cards for this user that match a - // supported type specified in |web_payment_request_|. - const std::vector<autofill::CreditCard*>& credit_cards() const { - return credit_cards_; + // Returns the available payment methods for this user that match a supported + // type specified in |web_payment_request_|. + const std::vector<payments::PaymentInstrument*>& payment_methods() const { + return payment_methods_; } - // Returns the currently selected credit card for this PaymentRequest flow if - // there is one. Returns nullptr if there is no selected credit card. - autofill::CreditCard* selected_credit_card() const { - return selected_credit_card_; + // Returns the currently selected payment method for this PaymentRequest flow + // if there is one. Returns nullptr if there is no selected payment method. + payments::PaymentInstrument* selected_payment_method() const { + return selected_payment_method_; } - // Sets the currently selected credit card for this PaymentRequest flow. - void set_selected_credit_card(autofill::CreditCard* credit_card) { - selected_credit_card_ = credit_card; + // Sets the currently selected payment method for this PaymentRequest flow. + void set_selected_payment_method( + payments::PaymentInstrument* payment_method) { + selected_payment_method_ = payment_method; } // Returns the available shipping options from |web_payment_request_|. @@ -216,14 +219,14 @@ // cached profiles ordered by completeness. void PopulateAvailableProfiles(); - // Fetches the autofill credit cards for this user from the - // PersonalDataManager that match a supported type specified in - // |web_payment_request_| and stores copies of them, owned by this - // PaymentRequest, in credit_card_cache_. - void PopulateCreditCardCache(); + // Fetches the payment methods for this user that match a supported type + // specified in |web_payment_request_| and stores copies of them, owned + // by this PaymentRequest, in payment_method_cache_. + void PopulatePaymentMethodCache(); - // Sets the available credit cards as references to the cached credit cards. - void PopulateAvailableCreditCards(); + // Sets the available payment methods as references to the cached payment + // methods. + void PopulateAvailablePaymentMethods(); // Sets the available shipping options as references to the shipping options // in |web_payment_request_|. @@ -264,14 +267,16 @@ std::vector<autofill::AutofillProfile*> contact_profiles_; autofill::AutofillProfile* selected_contact_profile_; - // Credit cards returnd by the Data Manager may change due to (e.g.) - // sync events, meaning PaymentRequest may outlive them. Therefore, credit - // cards are fetched once and their copies are cached here. Whenever credit - // cards are requested a vector of pointers to these copies are returned. - std::vector<std::unique_ptr<autofill::CreditCard>> credit_card_cache_; + // Some payment methods, such as credit cards returned by the Data Manager, + // may change due to (e.g.) sync events, meaning PaymentRequest may outlive + // them. Therefore, payment methods are fetched once and their copies are + // cached here. Whenever payment methods are requested a vector of pointers to + // these copies are returned. + std::vector<std::unique_ptr<payments::PaymentInstrument>> + payment_method_cache_; - std::vector<autofill::CreditCard*> credit_cards_; - autofill::CreditCard* selected_credit_card_; + std::vector<payments::PaymentInstrument*> payment_methods_; + payments::PaymentInstrument* selected_payment_method_; // A vector of supported basic card networks. This encompasses everything that // the merchant supports and should be used for support checks.
diff --git a/ios/chrome/browser/payments/payment_request.mm b/ios/chrome/browser/payments/payment_request.mm index 091c41c..b61fe86 100644 --- a/ios/chrome/browser/payments/payment_request.mm +++ b/ios/chrome/browser/payments/payment_request.mm
@@ -16,7 +16,9 @@ #include "components/autofill/core/browser/region_data_loader_impl.h" #include "components/autofill/core/browser/validation.h" #include "components/payments/core/address_normalizer_impl.h" +#include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/currency_formatter.h" +#include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_request_data_util.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/signin_manager.h" @@ -64,15 +66,15 @@ GetAddressInputStorage())), selected_shipping_profile_(nullptr), selected_contact_profile_(nullptr), - selected_credit_card_(nullptr), + selected_payment_method_(nullptr), selected_shipping_option_(nullptr), profile_comparator_(GetApplicationContext()->GetApplicationLocale(), *this) { PopulateAvailableShippingOptions(); PopulateProfileCache(); PopulateAvailableProfiles(); - PopulateCreditCardCache(); - PopulateAvailableCreditCards(); + PopulatePaymentMethodCache(); + PopulateAvailablePaymentMethods(); SetSelectedShippingOption(); @@ -94,17 +96,15 @@ } } - // TODO(crbug.com/702063): Change this code to prioritize credit cards by use - // count and other means. - auto first_complete_credit_card = std::find_if( - credit_cards_.begin(), credit_cards_.end(), - [this](const autofill::CreditCard* credit_card) { - DCHECK(credit_card); - return payment_request_util::IsCreditCardCompleteForPayment( - *credit_card, billing_profiles()); - }); - if (first_complete_credit_card != credit_cards_.end()) - selected_credit_card_ = *first_complete_credit_card; + // TODO(crbug.com/702063): Change this code to prioritize payment methods by + // use count and other means. + auto first_complete_payment_method = + std::find_if(payment_methods_.begin(), payment_methods_.end(), + [this](payments::PaymentInstrument* payment_method) { + return payment_method->IsCompleteForPayment(); + }); + if (first_complete_payment_method != payment_methods_.end()) + selected_payment_method_ = *first_complete_payment_method; } PaymentRequest::~PaymentRequest() {} @@ -135,10 +135,8 @@ const autofill::CreditCard& credit_card, base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate> result_delegate) { - // TODO: In the follow-up CL openFullCardRequestUI will take in arguments, - // specifically the |result_delegate| to be used in the - // |payment_request_ui_delegate_| object. - [payment_request_ui_delegate_ openFullCardRequestUI]; + [payment_request_ui_delegate_ requestFullCreditCard:credit_card + resultDelegate:result_delegate]; } payments::AddressNormalizer* PaymentRequest::GetAddressNormalizer() { @@ -253,14 +251,49 @@ profile_comparator_.FilterProfilesForShipping(raw_profiles_for_filtering); } -autofill::CreditCard* PaymentRequest::AddCreditCard( +payments::AutofillPaymentInstrument* +PaymentRequest::AddAutofillPaymentInstrument( const autofill::CreditCard& credit_card) { - credit_card_cache_.push_back( - base::MakeUnique<autofill::CreditCard>(credit_card)); + std::string basic_card_issuer_network = + autofill::data_util::GetPaymentRequestData(credit_card.network()) + .basic_card_issuer_network; - PopulateAvailableCreditCards(); + if (!base::ContainsValue(supported_card_networks_, + basic_card_issuer_network) || + !supported_card_types_set_.count(credit_card.card_type())) { + return nullptr; + } - return credit_card_cache_.back().get(); + // If the merchant specified the card network as part of the "basic-card" + // payment method, use "basic-card" as the method_name. Otherwise, use + // the name of the network directly. + std::string method_name = basic_card_issuer_network; + if (basic_card_specified_networks_.count(basic_card_issuer_network)) { + method_name = "basic_card"; + } + + // The total number of card types: credit, debit, prepaid, unknown. + constexpr size_t kTotalNumberOfCardTypes = 4U; + + // Whether the card type (credit, debit, prepaid) matches the type that the + // merchant has requested exactly. This should be false for unknown card + // types, if the merchant cannot accept some card types. + bool matches_merchant_card_type_exactly = + credit_card.card_type() != autofill::CreditCard::CARD_TYPE_UNKNOWN || + supported_card_types_set_.size() == kTotalNumberOfCardTypes; + + // AutofillPaymentInstrument makes a copy of |credit_card| so it is + // effectively owned by this object. + payment_method_cache_.push_back( + base::MakeUnique<payments::AutofillPaymentInstrument>( + method_name, credit_card, matches_merchant_card_type_exactly, + billing_profiles(), GetApplicationContext()->GetApplicationLocale(), + this)); + + PopulateAvailablePaymentMethods(); + + return static_cast<payments::AutofillPaymentInstrument*>( + payment_method_cache_.back().get()); } payments::PaymentsProfileComparator* PaymentRequest::profile_comparator() { @@ -268,17 +301,10 @@ } bool PaymentRequest::CanMakePayment() const { - for (const autofill::CreditCard* credit_card : credit_cards_) { - DCHECK(credit_card); - autofill::CreditCardCompletionStatus status = - autofill::GetCompletionStatusForCard( - *credit_card, GetApplicationContext()->GetApplicationLocale(), - billing_profiles()); - // A card only has to have a cardholder name and a number for the purposes - // of CanMakePayment. An expired card or one without a billing address is - // valid for this purpose. - return !(status & autofill::CREDIT_CARD_NO_CARDHOLDER || - status & autofill::CREDIT_CARD_NO_NUMBER); + for (payments::PaymentInstrument* payment_method : payment_methods_) { + if (payment_method->IsValidForCanMakePayment()) { + return true; + } } return false; } @@ -299,11 +325,10 @@ } } - DCHECK(selected_credit_card_); - personal_data_manager_->RecordUseOf(*selected_credit_card_); + selected_payment_method_->RecordUse(); } -void PaymentRequest::PopulateCreditCardCache() { +void PaymentRequest::PopulatePaymentMethodCache() { for (const payments::PaymentMethodData& method_data_entry : web_payment_request_.method_data) { for (const std::string& method : method_data_entry.supported_methods) { @@ -325,30 +350,25 @@ if (credit_cards_to_suggest.empty()) return; - credit_card_cache_.reserve(credit_cards_to_suggest.size()); + // TODO(crbug.com/602666): Determine number of possible payments so + // that we can appropriate reserve space in the following vector. - for (const auto* credit_card : credit_cards_to_suggest) { - std::string spec_issuer_network = - autofill::data_util::GetPaymentRequestData(credit_card->network()) - .basic_card_issuer_network; - if (base::ContainsValue(supported_card_networks_, spec_issuer_network)) { - credit_card_cache_.push_back( - base::MakeUnique<autofill::CreditCard>(*credit_card)); - } - } + payment_method_cache_.reserve(credit_cards_to_suggest.size()); + + for (const auto* credit_card : credit_cards_to_suggest) + AddAutofillPaymentInstrument(*credit_card); } -void PaymentRequest::PopulateAvailableCreditCards() { - if (credit_card_cache_.empty()) +void PaymentRequest::PopulateAvailablePaymentMethods() { + if (payment_method_cache_.empty()) return; - credit_cards_.clear(); - credit_cards_.reserve(credit_card_cache_.size()); + payment_methods_.clear(); + payment_methods_.reserve(payment_method_cache_.size()); - // TODO(crbug.com/602666): Implement prioritization rules for credit cards. - for (auto const& credit_card : credit_card_cache_) { - credit_cards_.push_back(credit_card.get()); - } + // TODO(crbug.com/602666): Implement prioritization rules for payment methods. + for (auto const& payment_method : payment_method_cache_) + payment_methods_.push_back(payment_method.get()); } void PaymentRequest::PopulateAvailableShippingOptions() {
diff --git a/ios/chrome/browser/payments/payment_request_unittest.mm b/ios/chrome/browser/payments/payment_request_unittest.mm index b6383c6..b01fe09c 100644 --- a/ios/chrome/browser/payments/payment_request_unittest.mm +++ b/ios/chrome/browser/payments/payment_request_unittest.mm
@@ -10,6 +10,7 @@ #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/currency_formatter.h" #include "components/payments/core/payment_method_data.h" #include "ios/chrome/browser/application_context.h" @@ -265,8 +266,9 @@ EXPECT_EQ("unionpay", payment_request.supported_card_networks()[1]); } -// Tests that a credit card can be added to the list of available credit cards. -TEST_F(PaymentRequestTest, AddCreditCard) { +// Tests that an autofill payment instrumnt e.g., credit cards can be added +// to the list of available payment methods. +TEST_F(PaymentRequestTest, AddAutofillPaymentInstrument) { web::PaymentRequest web_payment_request; payments::PaymentMethodData method_datum; method_datum.supported_methods.push_back("basic-card"); @@ -281,14 +283,14 @@ TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); - EXPECT_EQ(1U, payment_request.credit_cards().size()); + EXPECT_EQ(1U, payment_request.payment_methods().size()); autofill::CreditCard credit_card_2 = autofill::test::GetCreditCard2(); - autofill::CreditCard* added_credit_card = - payment_request.AddCreditCard(credit_card_2); + payments::AutofillPaymentInstrument* added_credit_card = + payment_request.AddAutofillPaymentInstrument(credit_card_2); - EXPECT_EQ(2U, payment_request.credit_cards().size()); - EXPECT_EQ(credit_card_2, *added_credit_card); + EXPECT_EQ(2U, payment_request.payment_methods().size()); + EXPECT_EQ(credit_card_2, *added_credit_card->credit_card()); } // Tests that a profile can be added to the list of available profiles. @@ -491,7 +493,7 @@ // No payment methods are selected because none are available! TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); - EXPECT_EQ(nullptr, payment_request.selected_credit_card()); + EXPECT_EQ(nullptr, payment_request.selected_payment_method()); } // Test that loading expired credit cards works as expected. @@ -510,7 +512,12 @@ // credit_card is selected because expired cards are valid for payment. TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); - EXPECT_EQ(credit_card.guid(), payment_request.selected_credit_card()->guid()); + EXPECT_EQ(payment_request.selected_payment_method()->type(), + payments::PaymentInstrument::Type::AUTOFILL); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); + EXPECT_EQ(credit_card.guid(), payment_instrument->credit_card()->guid()); } // Test that loading complete payment methods works as expected. @@ -534,8 +541,10 @@ // model). TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); - EXPECT_EQ(credit_card2.guid(), - payment_request.selected_credit_card()->guid()); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); + EXPECT_EQ(credit_card2.guid(), payment_instrument->credit_card()->guid()); } // Test that loading incomplete payment methods works as expected. @@ -558,7 +567,10 @@ // because it is complete. TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); - EXPECT_EQ(credit_card.guid(), payment_request.selected_credit_card()->guid()); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); + EXPECT_EQ(credit_card.guid(), payment_instrument->credit_card()->guid()); } // Test that the use counts of the data models are updated as expected when @@ -585,11 +597,14 @@ TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); EXPECT_EQ(address.guid(), payment_request.selected_shipping_profile()->guid()); EXPECT_EQ(contact_info.guid(), payment_request.selected_contact_profile()->guid()); - EXPECT_EQ(credit_card.guid(), payment_request.selected_credit_card()->guid()); + EXPECT_EQ(credit_card.guid(), payment_instrument->credit_card()->guid()); EXPECT_CALL(personal_data_manager, RecordUseOf(GuidMatches(address.guid()))) .Times(1); @@ -618,10 +633,13 @@ TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); EXPECT_EQ(address.guid(), payment_request.selected_shipping_profile()->guid()); EXPECT_EQ(address.guid(), payment_request.selected_contact_profile()->guid()); - EXPECT_EQ(credit_card.guid(), payment_request.selected_credit_card()->guid()); + EXPECT_EQ(credit_card.guid(), payment_instrument->credit_card()->guid()); // Even though |address| is used for contact info, shipping address, and // credit_card's billing address, the stats should be updated only once. @@ -652,10 +670,13 @@ TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); EXPECT_EQ(address.guid(), payment_request.selected_shipping_profile()->guid()); EXPECT_EQ(nullptr, payment_request.selected_contact_profile()); - EXPECT_EQ(credit_card.guid(), payment_request.selected_credit_card()->guid()); + EXPECT_EQ(credit_card.guid(), payment_instrument->credit_card()->guid()); EXPECT_CALL(personal_data_manager, RecordUseOf(GuidMatches(address.guid()))) .Times(1); @@ -682,9 +703,12 @@ TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); EXPECT_EQ(nullptr, payment_request.selected_shipping_profile()); EXPECT_EQ(address.guid(), payment_request.selected_contact_profile()->guid()); - EXPECT_EQ(credit_card.guid(), payment_request.selected_credit_card()->guid()); + EXPECT_EQ(credit_card.guid(), payment_instrument->credit_card()->guid()); EXPECT_CALL(personal_data_manager, RecordUseOf(GuidMatches(address.guid()))) .Times(1); @@ -714,9 +738,12 @@ TestPaymentRequest payment_request(web_payment_request, &personal_data_manager); + payments::AutofillPaymentInstrument* payment_instrument = + static_cast<payments::AutofillPaymentInstrument*>( + payment_request.selected_payment_method()); EXPECT_EQ(nullptr, payment_request.selected_shipping_profile()); EXPECT_EQ(nullptr, payment_request.selected_contact_profile()); - EXPECT_EQ(credit_card.guid(), payment_request.selected_credit_card()->guid()); + EXPECT_EQ(credit_card.guid(), payment_instrument->credit_card()->guid()); EXPECT_CALL(personal_data_manager, RecordUseOf(GuidMatches(address.guid()))) .Times(0);
diff --git a/ios/chrome/browser/payments/payment_request_util.h b/ios/chrome/browser/payments/payment_request_util.h index 3bbb6d6..ddf6ab2e 100644 --- a/ios/chrome/browser/payments/payment_request_util.h +++ b/ios/chrome/browser/payments/payment_request_util.h
@@ -14,9 +14,12 @@ namespace autofill { class AutofillProfile; -class CreditCard; } // namespace autofill +namespace payments { +class PaymentInstrument; +} // namespace payments + class PaymentRequest; namespace payment_request_util { @@ -52,16 +55,10 @@ PaymentRequest& payment_request, const autofill::AutofillProfile& profile); -// Returns whether the credit card is complete to be used as a payment method -// without further editing. -BOOL IsCreditCardCompleteForPayment( - const autofill::CreditCard& credit_card, - const std::vector<autofill::AutofillProfile*>& billing_profiles); - // Helper function to create a notification label for what's missing from a -// credit card. Returns nil if the resulting label is empty. -NSString* GetPaymentMethodNotificationLabelFromCreditCard( - const autofill::CreditCard& credit_card, +// payment method. Returns nil if the resulting label is empty. +NSString* GetPaymentMethodNotificationLabelFromPaymentMethod( + payments::PaymentInstrument& payment_method, const std::vector<autofill::AutofillProfile*>& billing_profiles); // Returns the title for the shipping section of the payment summary view given
diff --git a/ios/chrome/browser/payments/payment_request_util.mm b/ios/chrome/browser/payments/payment_request_util.mm index 0759516..7464e1f6 100644 --- a/ios/chrome/browser/payments/payment_request_util.mm +++ b/ios/chrome/browser/payments/payment_request_util.mm
@@ -13,6 +13,7 @@ #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/validation.h" +#include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_request_data_util.h" #include "components/payments/core/strings_util.h" #include "components/strings/grit/components_strings.h" @@ -73,23 +74,10 @@ return !label.empty() ? base::SysUTF16ToNSString(label) : nil; } -BOOL IsCreditCardCompleteForPayment( - const autofill::CreditCard& credit_card, +NSString* GetPaymentMethodNotificationLabelFromPaymentMethod( + payments::PaymentInstrument& payment_method, const std::vector<autofill::AutofillProfile*>& billing_profiles) { - // EXPIRED cards are considered valid for payment. The user will be prompted - // to enter the new expiration at the CVC step. - return autofill::GetCompletionStatusForCard( - credit_card, GetApplicationContext()->GetApplicationLocale(), - billing_profiles) <= autofill::CREDIT_CARD_EXPIRED; -} - -NSString* GetPaymentMethodNotificationLabelFromCreditCard( - const autofill::CreditCard& credit_card, - const std::vector<autofill::AutofillProfile*>& billing_profiles) { - base::string16 label = autofill::GetCompletionMessageForCard( - autofill::GetCompletionStatusForCard( - credit_card, GetApplicationContext()->GetApplicationLocale(), - billing_profiles)); + base::string16 label = payment_method.GetMissingInfoLabel(); return !label.empty() ? base::SysUTF16ToNSString(label) : nil; }
diff --git a/ios/chrome/browser/payments/test_payment_request.h b/ios/chrome/browser/payments/test_payment_request.h index 6d0415f..fa0ff0e 100644 --- a/ios/chrome/browser/payments/test_payment_request.h +++ b/ios/chrome/browser/payments/test_payment_request.h
@@ -84,8 +84,8 @@ // Removes all the contact profiles. void ClearContactProfiles(); - // Removes all the credit cards. - void ClearCreditCards(); + // Removes all the payment methods. + void ClearPaymentMethods(); // Sets the currently selected shipping option for this PaymentRequest flow. void set_selected_shipping_option(web::PaymentShippingOption* option) {
diff --git a/ios/chrome/browser/payments/test_payment_request.mm b/ios/chrome/browser/payments/test_payment_request.mm index 171ba59..21ac093 100644 --- a/ios/chrome/browser/payments/test_payment_request.mm +++ b/ios/chrome/browser/payments/test_payment_request.mm
@@ -22,8 +22,8 @@ contact_profiles_.clear(); } -void TestPaymentRequest::ClearCreditCards() { - credit_cards_.clear(); +void TestPaymentRequest::ClearPaymentMethods() { + payment_methods_.clear(); } autofill::RegionDataLoader* TestPaymentRequest::GetRegionDataLoader() {
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h index 3797cb9..5a37438 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h +++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h
@@ -10,9 +10,9 @@ #import "ios/chrome/browser/ui/payments/billing_address_selection_coordinator.h" #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" -namespace autofill { -class CreditCard; -} // namespace autofill +namespace payments { +class AutofillPaymentInstrument; +} class PaymentRequest; @@ -22,11 +22,12 @@ @protocol CreditCardEditCoordinatorDelegate<NSObject> // Notifies the delegate that the user has finished editing or creating -// |creditCard|. |creditCard| will be a new credit card owned by the -// PaymentRequest object if no credit card instance was provided to the +// |paymentMethod|. |paymentMethod| will be a new payment method owned by the +// PaymentRequest object if no payment method instance was provided to the // coordinator. Otherwise, it will be the same edited instance. - (void)creditCardEditCoordinator:(CreditCardEditCoordinator*)coordinator - didFinishEditingCreditCard:(autofill::CreditCard*)creditCard; + didFinishEditingPaymentMethod: + (payments::AutofillPaymentInstrument*)paymentMethod; // Notifies the delegate that the user has chosen to cancel editing or creating // a credit card and return to the previous screen. @@ -44,9 +45,9 @@ PaymentRequestEditViewControllerDelegate, PaymentRequestEditViewControllerValidator> -// The credit card to be edited, if any. This pointer is not owned by this class -// and should outlive it. -@property(nonatomic, assign) autofill::CreditCard* creditCard; +// The payment method to be edited, if any. This pointer is not owned by this +// class and should outlive it. +@property(nonatomic, assign) payments::AutofillPaymentInstrument* paymentMethod; // The PaymentRequest object owning an instance of web::PaymentRequest as // provided by the page invoking the Payment Request API. This pointer is not
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm index b31867e..24a3f9d 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
@@ -15,6 +15,8 @@ #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_constants.h" #import "components/autofill/ios/browser/credit_card_util.h" +#include "components/payments/core/autofill_payment_instrument.h" +#include "components/payments/core/payment_instrument.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" @@ -69,6 +71,8 @@ @interface CreditCardEditCoordinator () +@property(nonatomic, assign) autofill::CreditCard* creditCard; + @property(nonatomic, strong) BillingAddressSelectionCoordinator* billingAddressSelectionCoordinator; @@ -85,9 +89,10 @@ @implementation CreditCardEditCoordinator -@synthesize creditCard = _creditCard; +@synthesize paymentMethod = _paymentMethod; @synthesize paymentRequest = _paymentRequest; @synthesize delegate = _delegate; +@synthesize creditCard = _creditCard; @synthesize billingAddressSelectionCoordinator = _billingAddressSelectionCoordinator; @synthesize addressEditCoordinator = _addressEditCoordinator; @@ -96,6 +101,8 @@ @synthesize mediator = _mediator; - (void)start { + _creditCard = _paymentMethod ? _paymentMethod->credit_card() : nil; + _editViewController = [[PaymentRequestEditViewController alloc] init]; // TODO(crbug.com/602666): Title varies depending on the missing fields. NSString* title = _creditCard @@ -238,8 +245,8 @@ if (saveCreditCard) _paymentRequest->GetPersonalDataManager()->AddCreditCard(creditCard); - // Add the credit card to the list of credit cards in |_paymentRequest|. - _creditCard = _paymentRequest->AddCreditCard(creditCard); + // Add the credit card to the list of payment methods in |_paymentRequest|. + _paymentMethod = _paymentRequest->AddAutofillPaymentInstrument(creditCard); } else { // Override the origin. creditCard.set_origin(autofill::kSettingsOrigin); @@ -257,7 +264,7 @@ } [_delegate creditCardEditCoordinator:self - didFinishEditingCreditCard:_creditCard]; + didFinishEditingPaymentMethod:_paymentMethod]; } - (void)paymentRequestEditViewControllerDidCancel:
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm index 282645f0..abef7ab 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator_unittest.mm
@@ -12,6 +12,8 @@ #include "base/test/scoped_task_environment.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/payments/core/autofill_payment_instrument.h" +#include "components/payments/core/payment_instrument.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type.h" @@ -40,8 +42,9 @@ MockPaymentRequest(web::PaymentRequest web_payment_request, autofill::PersonalDataManager* personal_data_manager) : TestPaymentRequest(web_payment_request, personal_data_manager) {} - MOCK_METHOD1(AddCreditCard, - autofill::CreditCard*(const autofill::CreditCard&)); + MOCK_METHOD1( + AddAutofillPaymentInstrument, + payments::AutofillPaymentInstrument*(const autofill::CreditCard&)); }; MATCHER_P5(CreditCardMatches, @@ -151,10 +154,10 @@ } // Tests that calling the view controller delegate method which signals that the -// user has finished creating a new credit card, causes the credit card to be -// added to the PaymentRequest instance and the corresponding coordinator -// delegate method to get called. The new credit card is expected to get added -// to the PersonalDataManager if user chooses to save it locally. +// user has finished creating a new payment method, causes the payment method to +// be added to the PaymentRequest instance and the corresponding coordinator +// delegate method to get called. The new payment method is expected to get +// added to the PersonalDataManager if user chooses to save it locally. TEST_F(PaymentRequestCreditCardEditCoordinatorTest, DidFinishCreatingWithSave) { UIViewController* base_view_controller = [[UIViewController alloc] init]; ScopedKeyWindow scoped_key_window_; @@ -168,9 +171,10 @@ id delegate = [OCMockObject mockForProtocol:@protocol(CreditCardEditCoordinatorDelegate)]; [[delegate expect] - creditCardEditCoordinator:coordinator - didFinishEditingCreditCard:static_cast<autofill::CreditCard*>( - [OCMArg anyPointer])]; + creditCardEditCoordinator:coordinator + didFinishEditingPaymentMethod:static_cast< + payments::AutofillPaymentInstrument*>( + [OCMArg anyPointer])]; [coordinator setDelegate:delegate]; EXPECT_EQ(nil, base_view_controller.presentedViewController); @@ -180,17 +184,17 @@ base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); EXPECT_NE(nil, base_view_controller.presentedViewController); - // Expect a credit card to be added to the PaymentRequest. + // Expect a payment method to be added to the PaymentRequest. EXPECT_CALL(*payment_request_, - AddCreditCard(CreditCardMatches("4111111111111111", "John Doe", - "12", "2090", "12345"))) + AddAutofillPaymentInstrument(CreditCardMatches( + "4111111111111111", "John Doe", "12", "2090", "12345"))) .Times(1); - // Expect a credit card to be added to the PersonalDataManager. + // Expect a payment method to be added to the PersonalDataManager. EXPECT_CALL(personal_data_manager_, AddCreditCard(CreditCardMatches("4111111111111111", "John Doe", "12", "2090", "12345"))) .Times(1); - // No credit card should get updated in the PersonalDataManager. + // No payment method should get updated in the PersonalDataManager. EXPECT_CALL(personal_data_manager_, UpdateCreditCard(_)).Times(0); // Call the controller delegate method. @@ -209,9 +213,9 @@ } // Tests that calling the view controller delegate method which signals that the -// user has finished creating a new credit card, causes the credit card to be -// added to the PaymentRequest instance and the corresponding coordinator -// delegate method to get called. The new credit card should not get added to +// user has finished creating a new payment method, causes the payment method to +// be added to the PaymentRequest instance and the corresponding coordinator +// delegate method to get called. The new payment method should not get added to // the PersonalDataManager if user chooses to not to save it locally. TEST_F(PaymentRequestCreditCardEditCoordinatorTest, DidFinishCreatingNoSave) { UIViewController* base_view_controller = [[UIViewController alloc] init]; @@ -226,9 +230,10 @@ id delegate = [OCMockObject mockForProtocol:@protocol(CreditCardEditCoordinatorDelegate)]; [[delegate expect] - creditCardEditCoordinator:coordinator - didFinishEditingCreditCard:static_cast<autofill::CreditCard*>( - [OCMArg anyPointer])]; + creditCardEditCoordinator:coordinator + didFinishEditingPaymentMethod:static_cast< + payments::AutofillPaymentInstrument*>( + [OCMArg anyPointer])]; [coordinator setDelegate:delegate]; EXPECT_EQ(nil, base_view_controller.presentedViewController); @@ -238,14 +243,14 @@ base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); EXPECT_NE(nil, base_view_controller.presentedViewController); - // Expect a credit card to be added to the PaymentRequest. + // Expect a payment method to be added to the PaymentRequest. EXPECT_CALL(*payment_request_, - AddCreditCard(CreditCardMatches("4111111111111111", "John Doe", - "12", "2090", "12345"))) + AddAutofillPaymentInstrument(CreditCardMatches( + "4111111111111111", "John Doe", "12", "2090", "12345"))) .Times(1); - // No credit card should get added to the PersonalDataManager. + // No payment method should get added to the PersonalDataManager. EXPECT_CALL(personal_data_manager_, AddCreditCard(_)).Times(0); - // No credit card should get updated in the PersonalDataManager. + // No payment method should get updated in the PersonalDataManager. EXPECT_CALL(personal_data_manager_, UpdateCreditCard(_)).Times(0); // Call the controller delegate method. @@ -264,9 +269,9 @@ } // Tests that calling the view controller delegate method which signals that the -// user has finished editing a credit card, causes the corresponding coordinator -// delegate method to get called. The credit card should not get re-added to the -// PaymentRequest nor the PersonalDataManager. +// user has finished editing a payment method, causes the corresponding +// coordinator delegate method to get called. The payment method should not get +// re-added to the PaymentRequest nor the PersonalDataManager. TEST_F(PaymentRequestCreditCardEditCoordinatorTest, DidFinishEditing) { UIViewController* base_view_controller = [[UIViewController alloc] init]; ScopedKeyWindow scoped_key_window_; @@ -276,17 +281,20 @@ initWithBaseViewController:base_view_controller]; [coordinator setPaymentRequest:payment_request_.get()]; - // Set the credit card to be edited. + // Set the payment method to be edited. autofill::CreditCard credit_card; - [coordinator setCreditCard:&credit_card]; + payments::AutofillPaymentInstrument payment_method( + "", credit_card, false, payment_request_->billing_profiles(), "", nil); + [coordinator setPaymentMethod:&payment_method]; // Mock the coordinator delegate. id delegate = [OCMockObject mockForProtocol:@protocol(CreditCardEditCoordinatorDelegate)]; [[delegate expect] - creditCardEditCoordinator:coordinator - didFinishEditingCreditCard:static_cast<autofill::CreditCard*>( - [OCMArg anyPointer])]; + creditCardEditCoordinator:coordinator + didFinishEditingPaymentMethod:static_cast< + payments::AutofillPaymentInstrument*>( + [OCMArg anyPointer])]; [coordinator setDelegate:delegate]; EXPECT_EQ(nil, base_view_controller.presentedViewController); @@ -296,11 +304,11 @@ base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); EXPECT_NE(nil, base_view_controller.presentedViewController); - // No credit card should get added to the PaymentRequest. - EXPECT_CALL(*payment_request_, AddCreditCard(_)).Times(0); - // No credit card should get added to the PersonalDataManager. + // No payment method should get added to the PaymentRequest. + EXPECT_CALL(*payment_request_, AddAutofillPaymentInstrument(_)).Times(0); + // No payment method should get added to the PersonalDataManager. EXPECT_CALL(personal_data_manager_, AddCreditCard(_)).Times(0); - // Expect a credit card to be updated in the PersonalDataManager. + // Expect a payment method to be updated in the PersonalDataManager. EXPECT_CALL(personal_data_manager_, UpdateCreditCard(CreditCardMatches("4111111111111111", "John Doe", "12", "2090", "12345"))) @@ -322,7 +330,7 @@ } // Tests that calling the view controller delegate method which signals that the -// user has chosen to cancel creating/editing a credit card, causes the +// user has chosen to cancel creating/editing a payment method, causes the // corresponding coordinator delegate method to get called. TEST_F(PaymentRequestCreditCardEditCoordinatorTest, DidCancel) { UIViewController* base_view_controller = [[UIViewController alloc] init];
diff --git a/ios/chrome/browser/ui/payments/full_card_requester.h b/ios/chrome/browser/ui/payments/full_card_requester.h index ea6f1a0..c6092c7 100644 --- a/ios/chrome/browser/ui/payments/full_card_requester.h +++ b/ios/chrome/browser/ui/payments/full_card_requester.h
@@ -5,14 +5,16 @@ #ifndef IOS_CHROME_BROWSER_UI_PAYMENTS_FULL_CARD_REQUESTER_H_ #define IOS_CHROME_BROWSER_UI_PAYMENTS_FULL_CARD_REQUESTER_H_ +#include <string> + #import <UIKit/UIKit.h> #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/payments/full_card_request.h" #include "components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.h" +#include "components/payments/core/payment_instrument.h" namespace autofill { class AutofillManager; @@ -25,19 +27,17 @@ @protocol FullCardRequesterConsumer -// Called when a credit card has been successfully unmasked. Note that |card| -// may be different from what passed to GetFullCard method of FullCardRequester, -// because CVC unmasking process may update the credit card number and -// expiration date. -- (void)fullCardRequestDidSucceedWithCard:(const autofill::CreditCard&)card - verificationCode: - (const base::string16&)verificationCode; +// Called when a credit card has been successfully unmasked. Should be +// called wth method name (e.g., "visa") and json-serialized details. +- (void)fullCardRequestDidSucceedWithMethodName:(const std::string&)methodName + stringifiedDetails: + (const std::string&)stringifiedDetails; @end // Receives the full credit card details. Also displays the unmask prompt UI. class FullCardRequester - : public autofill::payments::FullCardRequest::ResultDelegate, + : public payments::PaymentInstrument::Delegate, public autofill::payments::FullCardRequest::UIDelegate, public base::SupportsWeakPtr<FullCardRequester> { public: @@ -45,14 +45,17 @@ UIViewController* base_view_controller, ios::ChromeBrowserState* browser_state); - void GetFullCard(autofill::CreditCard* card, - autofill::AutofillManager* autofill_manager); - - // payments::FullCardRequest::ResultDelegate: - void OnFullCardRequestSucceeded( + void GetFullCard( const autofill::CreditCard& card, - const base::string16& verificationCode) override; - void OnFullCardRequestFailed() override; + autofill::AutofillManager* autofill_manager, + base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate> + result_delegate); + + // payments::PaymentInstrument::Delegate: + void OnInstrumentDetailsReady( + const std::string& method_name, + const std::string& stringified_details) override; + void OnInstrumentDetailsError() override{}; // payments::FullCardRequest::UIDelegate: void ShowUnmaskPrompt(
diff --git a/ios/chrome/browser/ui/payments/full_card_requester.mm b/ios/chrome/browser/ui/payments/full_card_requester.mm index 74cc6e4..55e0995 100644 --- a/ios/chrome/browser/ui/payments/full_card_requester.mm +++ b/ios/chrome/browser/ui/payments/full_card_requester.mm
@@ -51,27 +51,22 @@ browser_state->IsOffTheRecord()) {} void FullCardRequester::GetFullCard( - autofill::CreditCard* card, - autofill::AutofillManager* autofill_manager) { - DCHECK(card); - DCHECK(autofill_manager); - autofill_manager->GetOrCreateFullCardRequest()->GetFullCard( - *card, autofill::AutofillClient::UNMASK_FOR_PAYMENT_REQUEST, AsWeakPtr(), - AsWeakPtr()); -} - -void FullCardRequester::OnFullCardRequestSucceeded( const autofill::CreditCard& card, - const base::string16& verificationCode) { - [consumer_ fullCardRequestDidSucceedWithCard:card - verificationCode:verificationCode]; + autofill::AutofillManager* autofill_manager, + base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate> + result_delegate) { + DCHECK(autofill_manager); + DCHECK(result_delegate); + autofill_manager->GetOrCreateFullCardRequest()->GetFullCard( + card, autofill::AutofillClient::UNMASK_FOR_PAYMENT_REQUEST, + result_delegate, AsWeakPtr()); } -void FullCardRequester::OnFullCardRequestFailed() { - // No action is required here. PRCardUnmaskPromptViewBridge manages its own - // life cycle. When the prompt is explicitly dismissed via tapping the close - // button (either in presence or absence of an error), the unmask prompt - // dialog pops itself and the user is back to the Payment Request UI. +void FullCardRequester::OnInstrumentDetailsReady( + const std::string& method_name, + const std::string& stringified_details) { + [consumer_ fullCardRequestDidSucceedWithMethodName:method_name + stringifiedDetails:stringified_details]; } void FullCardRequester::ShowUnmaskPrompt(
diff --git a/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm b/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm index 13de877..d84f5e08 100644 --- a/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm +++ b/ios/chrome/browser/ui/payments/full_card_requester_unittest.mm
@@ -4,6 +4,10 @@ #import "ios/chrome/browser/ui/payments/full_card_requester.h" +#include <string> + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" @@ -12,6 +16,9 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/ios/browser/autofill_driver_ios.h" +#include "components/payments/core/autofill_payment_instrument.h" +#include "components/payments/core/basic_card_response.h" +#include "components/payments/core/payment_request_data_util.h" #import "ios/chrome/browser/autofill/autofill_agent.h" #import "ios/chrome/browser/autofill/autofill_controller.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" @@ -34,18 +41,40 @@ @implementation FullCardRequesterConsumerMock -typedef void (^mock_full_card_request_did_succeed)(const autofill::CreditCard&, - const base::string16&); +typedef void (^mock_full_card_request_did_succeed_with_method_name)( + const std::string&, + const std::string&); -- (void)fullCardRequestDidSucceedWithCard:(const autofill::CreditCard&)card - verificationCode: - (const base::string16&)verificationCode { - return static_cast<mock_full_card_request_did_succeed>( - [self blockForSelector:_cmd])(card, verificationCode); +- (void)fullCardRequestDidSucceedWithMethodName:(const std::string&)methodName + stringifiedDetails: + (const std::string&)stringifiedDetails { + return static_cast<mock_full_card_request_did_succeed_with_method_name>( + [self blockForSelector:_cmd])(methodName, stringifiedDetails); } @end +class FakeResultDelegate + : public autofill::payments::FullCardRequest::ResultDelegate { + public: + FakeResultDelegate() : weak_ptr_factory_(this) {} + ~FakeResultDelegate() override {} + + void OnFullCardRequestSucceeded(const autofill::CreditCard& card, + const base::string16& cvc) override {} + + void OnFullCardRequestFailed() override {} + + base::WeakPtr<FakeResultDelegate> GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + + private: + base::WeakPtrFactory<FakeResultDelegate> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeResultDelegate); +}; + class PaymentRequestFullCardRequesterTest : public ChromeWebTest { protected: PaymentRequestFullCardRequesterTest() @@ -98,7 +127,9 @@ autofill::AutofillManager* autofill_manager = autofill::AutofillDriverIOS::FromWebState(web_state()) ->autofill_manager(); - full_card_requester.GetFullCard(&credit_card_, autofill_manager); + FakeResultDelegate* fake_result_delegate = new FakeResultDelegate; + full_card_requester.GetFullCard(credit_card_, autofill_manager, + fake_result_delegate->GetWeakPtr()); // Spin the run loop to trigger the animation. base::test::ios::SpinRunLoopWithMaxDelay(base::TimeDelta::FromSecondsD(1.0)); @@ -119,23 +150,38 @@ // Tests that calling the FullCardRequester's delegate method which signals that // the full credit card details have been successfully received, causes the // FullCardRequester's delegate method to get called. -TEST_F(PaymentRequestFullCardRequesterTest, FullCardRequestSucceeded) { +TEST_F(PaymentRequestFullCardRequesterTest, InstrumentDetailsReady) { // Mock the consumer. id consumer = [OCMockObject mockForProtocol:@protocol(FullCardRequesterConsumer)]; id consumer_mock([[FullCardRequesterConsumerMock alloc] initWithRepresentedObject:consumer]); - SEL selector = @selector(fullCardRequestDidSucceedWithCard:verificationCode:); + SEL selector = + @selector(fullCardRequestDidSucceedWithMethodName:stringifiedDetails:); [consumer_mock onSelector:selector - callBlockExpectation:^(const autofill::CreditCard& card, - const base::string16& verificationCode) { - EXPECT_EQ(credit_card_, card); - EXPECT_EQ(base::ASCIIToUTF16("123"), verificationCode); + callBlockExpectation:^(const std::string& methodName, + const std::string& stringifiedDetails) { + EXPECT_EQ("visa", methodName); + + std::string cvc; + std::unique_ptr<base::DictionaryValue> detailsDict = + base::DictionaryValue::From( + base::JSONReader::Read(stringifiedDetails)); + detailsDict->GetString("cardSecurityCode", &cvc); + EXPECT_EQ("123", cvc); }]; FullCardRequester full_card_requester(consumer_mock, nil, chrome_browser_state_.get()); - full_card_requester.OnFullCardRequestSucceeded(credit_card_, - base::ASCIIToUTF16("123")); + autofill::AutofillProfile billing_address; + + std::unique_ptr<base::DictionaryValue> response_value = + payments::data_util::GetBasicCardResponseFromAutofillCreditCard( + credit_card_, base::ASCIIToUTF16("123"), billing_address, "en-US") + .ToDictionaryValue(); + std::string stringifiedDetails; + base::JSONWriter::Write(*response_value, &stringifiedDetails); + + full_card_requester.OnInstrumentDetailsReady("visa", stringifiedDetails); }
diff --git a/ios/chrome/browser/ui/payments/payment_items_display_coordinator.mm b/ios/chrome/browser/ui/payments/payment_items_display_coordinator.mm index 027990af..44a8349 100644 --- a/ios/chrome/browser/ui/payments/payment_items_display_coordinator.mm +++ b/ios/chrome/browser/ui/payments/payment_items_display_coordinator.mm
@@ -26,7 +26,7 @@ @synthesize delegate = _delegate; - (void)start { - BOOL payButtonEnabled = _paymentRequest->selected_credit_card() != nil; + BOOL payButtonEnabled = _paymentRequest->selected_payment_method() != nil; _viewController = [[PaymentItemsDisplayViewController alloc] initWithPayButtonEnabled:payButtonEnabled]; [_viewController setDelegate:self];
diff --git a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.h b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.h index c644675..fd1b1c1f 100644 --- a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.h +++ b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.h
@@ -14,9 +14,9 @@ class PaymentRequest; -namespace autofill { -class CreditCard; -} // namespace autofill +namespace payments { +class PaymentInstrument; +} // namespace payments @class PaymentMethodSelectionCoordinator; @@ -26,7 +26,8 @@ // Notifies the delegate that the user has selected a payment method. - (void)paymentMethodSelectionCoordinator: (PaymentMethodSelectionCoordinator*)coordinator - didSelectPaymentMethod:(autofill::CreditCard*)paymentMethod; + didSelectPaymentMethod: + (payments::PaymentInstrument*)paymentMethod; // Notifies the delegate that the user has chosen to return to the previous // screen without making a selection.
diff --git a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm index 8441248..f4e2771 100644 --- a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm +++ b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator.mm
@@ -8,6 +8,8 @@ #include "base/logging.h" #include "components/autofill/core/browser/credit_card.h" +#include "components/payments/core/autofill_payment_instrument.h" +#include "components/payments/core/payment_instrument.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/ui/payments/cells/payment_method_item.h" @@ -33,16 +35,17 @@ @property(nonatomic, strong) PaymentMethodSelectionMediator* mediator; -// Initializes and starts the CreditCardEditCoordinator. Sets |creditCard| as -// the credit card to be edited. -- (void)startCreditCardEditCoordinatorWithCreditCard: - (autofill::CreditCard*)creditCard; +// Initializes and starts the CreditCardEditCoordinator. Sets +// |autofillInstrument| as the autofill payment instrument to be edited. +- (void)startCreditCardEditCoordinatorWithAutofillPaymentInstrument: + (payments::AutofillPaymentInstrument*)autofillInstrument; // Called when the user selects a payment method. The cell is checked, the // UI is locked so that the user can't interact with it, then the delegate is // notified. The delay is here to let the user get a visual feedback of the // selection before this view disappears. -- (void)delayedNotifyDelegateOfSelection:(autofill::CreditCard*)paymentMethod; +- (void)delayedNotifyDelegateOfSelection: + (payments::PaymentInstrument*)paymentMethod; @end @@ -83,20 +86,25 @@ - (BOOL)paymentRequestSelectorViewController: (PaymentRequestSelectorViewController*)controller didSelectItemAtIndex:(NSUInteger)index { - DCHECK(index < self.paymentRequest->credit_cards().size()); - autofill::CreditCard* creditCard = self.paymentRequest->credit_cards()[index]; + DCHECK(index < self.paymentRequest->payment_methods().size()); + payments::PaymentInstrument* paymentMethod = + self.paymentRequest->payment_methods()[index]; // Proceed with item selection only if the item has all required info, or - // else bring up the credit card editor. + // else bring up the credit card editor. A payment method can be incomplete + // only if it is an AutofillPaymentInstrument. CollectionViewItem<PaymentsIsSelectable>* selectedItem = self.mediator.selectableItems[index]; if (selectedItem.complete) { // Update the data source with the selection. self.mediator.selectedItemIndex = index; - [self delayedNotifyDelegateOfSelection:creditCard]; + [self delayedNotifyDelegateOfSelection:paymentMethod]; return YES; } else { - [self startCreditCardEditCoordinatorWithCreditCard:creditCard]; + DCHECK(paymentMethod->type() == + payments::PaymentInstrument::Type::AUTOFILL); + [self startCreditCardEditCoordinatorWithAutofillPaymentInstrument: + static_cast<payments::AutofillPaymentInstrument*>(paymentMethod)]; return NO; } } @@ -108,7 +116,7 @@ - (void)paymentRequestSelectorViewControllerDidSelectAddItem: (PaymentRequestSelectorViewController*)controller { - [self startCreditCardEditCoordinatorWithCreditCard:nil]; + [self startCreditCardEditCoordinatorWithAutofillPaymentInstrument:nil]; } - (void)paymentRequestSelectorViewControllerDidToggleEditingMode: @@ -120,33 +128,41 @@ - (void)paymentRequestSelectorViewController: (PaymentRequestSelectorViewController*)controller didSelectItemAtIndexForEditing:(NSUInteger)index { - DCHECK(index < self.paymentRequest->credit_cards().size()); - [self - startCreditCardEditCoordinatorWithCreditCard:self.paymentRequest - ->credit_cards()[index]]; + DCHECK(index < self.paymentRequest->payment_methods().size()); + + // We should only edit the payment instrument if it is an + // AutofillPaymentInstrument. + if (self.paymentRequest->payment_methods()[index]->type() == + payments::PaymentInstrument::Type::AUTOFILL) { + [self startCreditCardEditCoordinatorWithAutofillPaymentInstrument: + static_cast<payments::AutofillPaymentInstrument*>( + self.paymentRequest->payment_methods()[index])]; + } } #pragma mark - CreditCardEditCoordinatorDelegate - (void)creditCardEditCoordinator:(CreditCardEditCoordinator*)coordinator - didFinishEditingCreditCard:(autofill::CreditCard*)creditCard { + didFinishEditingPaymentMethod: + (payments::AutofillPaymentInstrument*)creditCard { // Update the data source with the new data. [self.mediator loadItems]; - const std::vector<autofill::CreditCard*>& creditCards = - self.paymentRequest->credit_cards(); - auto position = std::find(creditCards.begin(), creditCards.end(), creditCard); - DCHECK(position != creditCards.end()); + const std::vector<payments::PaymentInstrument*>& paymentMethods = + self.paymentRequest->payment_methods(); + auto position = + std::find(paymentMethods.begin(), paymentMethods.end(), creditCard); + DCHECK(position != paymentMethods.end()); // Mark the edited item as complete meaning all required information has been // filled out. CollectionViewItem<PaymentsIsSelectable>* editedItem = - self.mediator.selectableItems[position - creditCards.begin()]; + self.mediator.selectableItems[position - paymentMethods.begin()]; editedItem.complete = YES; if (![self.viewController isEditing]) { // Update the data source with the selection. - self.mediator.selectedItemIndex = position - creditCards.begin(); + self.mediator.selectedItemIndex = position - paymentMethods.begin(); } [self.viewController loadModel]; @@ -170,17 +186,18 @@ #pragma mark - Helper methods -- (void)startCreditCardEditCoordinatorWithCreditCard: - (autofill::CreditCard*)creditCard { +- (void)startCreditCardEditCoordinatorWithAutofillPaymentInstrument: + (payments::AutofillPaymentInstrument*)autofillInstrument { self.creditCardEditCoordinator = [[CreditCardEditCoordinator alloc] initWithBaseViewController:self.viewController]; self.creditCardEditCoordinator.paymentRequest = self.paymentRequest; - self.creditCardEditCoordinator.creditCard = creditCard; + self.creditCardEditCoordinator.paymentMethod = autofillInstrument; self.creditCardEditCoordinator.delegate = self; [self.creditCardEditCoordinator start]; } -- (void)delayedNotifyDelegateOfSelection:(autofill::CreditCard*)paymentMethod { +- (void)delayedNotifyDelegateOfSelection: + (payments::PaymentInstrument*)paymentMethod { self.viewController.view.userInteractionEnabled = NO; __weak PaymentMethodSelectionCoordinator* weakSelf = self; dispatch_after(
diff --git a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm index 145efaf..bfa1995 100644 --- a/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_method_selection_coordinator_unittest.mm
@@ -12,6 +12,7 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/payments/core/payment_instrument.h" #include "ios/chrome/browser/payments/payment_request.h" #include "ios/chrome/browser/payments/payment_request_test_util.h" #include "ios/chrome/browser/payments/test_payment_request.h" @@ -106,10 +107,10 @@ mockForProtocol:@protocol(PaymentMethodSelectionCoordinatorDelegate)]; [[delegate expect] paymentMethodSelectionCoordinator:coordinator - didSelectPaymentMethod:payment_request_->credit_cards()[0]]; + didSelectPaymentMethod:payment_request_->payment_methods()[0]]; [[delegate reject] paymentMethodSelectionCoordinator:coordinator - didSelectPaymentMethod:payment_request_->credit_cards()[1]]; + didSelectPaymentMethod:payment_request_->payment_methods()[1]]; [coordinator setDelegate:delegate]; EXPECT_EQ(1u, navigation_controller.viewControllers.count);
diff --git a/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm b/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm index 4513447e..1706d06 100644 --- a/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm +++ b/ios/chrome/browser/ui/payments/payment_method_selection_mediator.mm
@@ -8,10 +8,11 @@ #include "base/strings/string16.h" #include "base/strings/sys_string_conversions.h" -#include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/personal_data_manager.h" +#include "components/payments/core/autofill_payment_instrument.h" +#include "components/payments/core/payment_instrument.h" #include "components/payments/core/strings_util.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/payments/payment_request.h" @@ -28,6 +29,8 @@ namespace { using ::payment_request_util::GetBillingAddressLabelFromAutofillProfile; +using ::payment_request_util:: + GetPaymentMethodNotificationLabelFromPaymentMethod; } // namespace @interface PaymentMethodSelectionMediator () @@ -90,39 +93,36 @@ #pragma mark - Public methods - (void)loadItems { - const std::vector<autofill::CreditCard*>& paymentMethods = - _paymentRequest->credit_cards(); + const std::vector<payments::PaymentInstrument*>& paymentMethods = + _paymentRequest->payment_methods(); _items = [NSMutableArray arrayWithCapacity:paymentMethods.size()]; for (size_t index = 0; index < paymentMethods.size(); ++index) { - autofill::CreditCard* paymentMethod = paymentMethods[index]; + payments::PaymentInstrument* paymentMethod = paymentMethods[index]; DCHECK(paymentMethod); PaymentMethodItem* item = [[PaymentMethodItem alloc] init]; - item.methodID = - base::SysUTF16ToNSString(paymentMethod->NetworkAndLastFourDigits()); - item.methodDetail = base::SysUTF16ToNSString( - paymentMethod->GetRawInfo(autofill::CREDIT_CARD_NAME_FULL)); - item.notification = - payment_request_util::GetPaymentMethodNotificationLabelFromCreditCard( - *paymentMethod, _paymentRequest->billing_profiles()); - item.complete = payment_request_util::IsCreditCardCompleteForPayment( + item.methodID = base::SysUTF16ToNSString(paymentMethod->GetLabel()); + item.methodDetail = base::SysUTF16ToNSString(paymentMethod->GetSublabel()); + item.notification = GetPaymentMethodNotificationLabelFromPaymentMethod( *paymentMethod, _paymentRequest->billing_profiles()); + item.complete = paymentMethod->IsCompleteForPayment(); - autofill::AutofillProfile* billingAddress = - autofill::PersonalDataManager::GetProfileFromProfilesByGUID( - paymentMethod->billing_address_id(), - _paymentRequest->billing_profiles()); - if (billingAddress) { - item.methodAddress = - GetBillingAddressLabelFromAutofillProfile(*billingAddress); + if (paymentMethod->type() == payments::PaymentInstrument::Type::AUTOFILL) { + payments::AutofillPaymentInstrument* autofillInstrument = + static_cast<payments::AutofillPaymentInstrument*>(paymentMethod); + autofill::AutofillProfile* billingAddress = + autofill::PersonalDataManager::GetProfileFromProfilesByGUID( + autofillInstrument->credit_card()->billing_address_id(), + _paymentRequest->billing_profiles()); + if (billingAddress) { + item.methodAddress = + GetBillingAddressLabelFromAutofillProfile(*billingAddress); + } } - int methodTypeIconID = - autofill::data_util::GetPaymentRequestData(paymentMethod->network()) - .icon_resource_id; - item.methodTypeIcon = NativeImage(methodTypeIconID); + item.methodTypeIcon = NativeImage(paymentMethod->icon_resource_id()); item.reserveRoomForAccessoryType = YES; - if (_paymentRequest->selected_credit_card() == paymentMethod) + if (_paymentRequest->selected_payment_method() == paymentMethod) _selectedItemIndex = index; [_items addObject:item];
diff --git a/ios/chrome/browser/ui/payments/payment_request_coordinator.h b/ios/chrome/browser/ui/payments/payment_request_coordinator.h index aa70e22..90779d4b 100644 --- a/ios/chrome/browser/ui/payments/payment_request_coordinator.h +++ b/ios/chrome/browser/ui/payments/payment_request_coordinator.h
@@ -9,6 +9,7 @@ #include "base/ios/block_types.h" #include "base/strings/string16.h" +#include "components/autofill/core/browser/payments/full_card_request.h" #import "ios/chrome/browser/chrome_coordinator.h" #import "ios/chrome/browser/ui/payments/address_edit_coordinator.h" #import "ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h" @@ -51,10 +52,11 @@ - (void)paymentRequestCoordinatorDidSelectSettings: (PaymentRequestCoordinator*)coordinator; -// Notifies the delegate that the user has completed the payment request. +// Notifies the delegate that the full payment method name and details +// have been receieved. - (void)paymentRequestCoordinator:(PaymentRequestCoordinator*)coordinator - didCompletePaymentRequestWithCard:(const autofill::CreditCard&)card - verificationCode:(const base::string16&)verificationCode; + didReceiveFullMethodName:(const std::string&)methodName + stringifiedDetails:(const std::string&)stringifiedDetails; // Notifies the delegate that the user has selected a shipping address. - (void)paymentRequestCoordinator:(PaymentRequestCoordinator*)coordinator @@ -115,8 +117,12 @@ // The delegate to be notified when the user confirms or cancels the request. @property(nonatomic, weak) id<PaymentRequestCoordinatorDelegate> delegate; -// Initiates the UI that will process payment with a payment method. -- (void)sendPaymentResponse; +// Initiates the UI that will request card details from the user. +- (void) +requestFullCreditCard:(const autofill::CreditCard&)card + resultDelegate: + (base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>) + resultDelegate; // Updates the payment details of the PaymentRequest and updates the UI. - (void)updatePaymentDetails:(web::PaymentDetails)paymentDetails;
diff --git a/ios/chrome/browser/ui/payments/payment_request_coordinator.mm b/ios/chrome/browser/ui/payments/payment_request_coordinator.mm index f316eef..415e014 100644 --- a/ios/chrome/browser/ui/payments/payment_request_coordinator.mm +++ b/ios/chrome/browser/ui/payments/payment_request_coordinator.mm
@@ -4,10 +4,14 @@ #import "ios/chrome/browser/ui/payments/payment_request_coordinator.h" +#include "base/json/json_reader.h" #include "base/memory/ptr_util.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" +#include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/payment_address.h" +#include "components/payments/core/payment_instrument.h" +#include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" @@ -80,6 +84,9 @@ setModalTransitionStyle:UIModalTransitionStyleCoverVertical]; [_navigationController setNavigationBarHidden:YES]; + _fullCardRequester = base::MakeUnique<FullCardRequester>( + self, _navigationController, _browserState); + [[self baseViewController] presentViewController:_navigationController animated:YES completion:nil]; @@ -113,27 +120,27 @@ _navigationController = nil; } -- (void)sendPaymentResponse { - DCHECK(_paymentRequest->selected_credit_card()); - autofill::CreditCard* card = _paymentRequest->selected_credit_card(); - _fullCardRequester = base::MakeUnique<FullCardRequester>( - self, _navigationController, _browserState); - _fullCardRequester->GetFullCard(card, _autofillManager); +- (void) +requestFullCreditCard:(const autofill::CreditCard&)card + resultDelegate: + (base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>) + resultDelegate { + _fullCardRequester->GetFullCard(card, _autofillManager, resultDelegate); } #pragma mark - FullCardRequesterConsumer -- (void)fullCardRequestDidSucceedWithCard:(const autofill::CreditCard&)card - verificationCode: - (const base::string16&)verificationCode { +- (void)fullCardRequestDidSucceedWithMethodName:(const std::string&)methodName + stringifiedDetails: + (const std::string&)stringifiedDetails { _viewController.view.userInteractionEnabled = NO; [_viewController setPending:YES]; [_viewController loadModel]; [[_viewController collectionView] reloadData]; [_delegate paymentRequestCoordinator:self - didCompletePaymentRequestWithCard:card - verificationCode:verificationCode]; + didReceiveFullMethodName:methodName + stringifiedDetails:stringifiedDetails]; } #pragma mark - Public methods @@ -210,7 +217,9 @@ - (void)paymentRequestViewControllerDidConfirm: (PaymentRequestViewController*)controller { - [self sendPaymentResponse]; + DCHECK(_paymentRequest->selected_payment_method()); + _paymentRequest->selected_payment_method()->InvokePaymentApp( + _fullCardRequester.get()); } - (void)paymentRequestViewControllerDidSelectSettings: @@ -286,7 +295,7 @@ - (void)paymentRequestViewControllerDidSelectPaymentMethodItem: (PaymentRequestViewController*)controller { - if (_paymentRequest->credit_cards().empty()) { + if (_paymentRequest->payment_methods().empty()) { _creditCardEditCoordinator = [[CreditCardEditCoordinator alloc] initWithBaseViewController:_viewController]; [_creditCardEditCoordinator setPaymentRequest:_paymentRequest]; @@ -327,7 +336,9 @@ - (void)paymentItemsDisplayCoordinatorDidConfirm: (PaymentItemsDisplayCoordinator*)coordinator { - [self sendPaymentResponse]; + DCHECK(_paymentRequest->selected_payment_method()); + _paymentRequest->selected_payment_method()->InvokePaymentApp( + _fullCardRequester.get()); } #pragma mark - ContactInfoSelectionCoordinatorDelegate @@ -421,11 +432,11 @@ - (void)paymentMethodSelectionCoordinator: (PaymentMethodSelectionCoordinator*)coordinator - didSelectPaymentMethod:(autofill::CreditCard*)creditCard { - DCHECK(creditCard); - DCHECK(payment_request_util::IsCreditCardCompleteForPayment( - *creditCard, _paymentRequest->billing_profiles())); - _paymentRequest->set_selected_credit_card(creditCard); + didSelectPaymentMethod: + (payments::PaymentInstrument*)paymentMethod { + DCHECK(paymentMethod); + DCHECK(paymentMethod->IsCompleteForPayment()); + _paymentRequest->set_selected_payment_method(paymentMethod); [_viewController updatePaymentMethodSection]; [_methodSelectionCoordinator stop]; @@ -441,9 +452,11 @@ #pragma mark - CreditCardEditCoordinatorDelegate - (void)creditCardEditCoordinator:(CreditCardEditCoordinator*)coordinator - didFinishEditingCreditCard:(autofill::CreditCard*)creditCard { - DCHECK(creditCard); - _paymentRequest->set_selected_credit_card(creditCard); + didFinishEditingPaymentMethod: + (payments::AutofillPaymentInstrument*)paymentMethod { + DCHECK(paymentMethod); + DCHECK(paymentMethod->IsCompleteForPayment()); + _paymentRequest->set_selected_payment_method(paymentMethod); [_viewController updatePaymentMethodSection]; [_creditCardEditCoordinator stop];
diff --git a/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm index 1f6c030..736c14b6 100644 --- a/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_coordinator_unittest.mm
@@ -4,15 +4,21 @@ #import "ios/chrome/browser/ui/payments/payment_request_coordinator.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/mac/foundation_util.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/ios/wait_util.h" +#include "base/test/scoped_task_environment.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/payment_address.h" +#include "components/payments/core/payment_instrument.h" +#include "components/payments/core/payment_request_data_util.h" #include "components/payments/core/payments_test_util.h" #include "components/prefs/pref_service.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" @@ -43,8 +49,8 @@ typedef void (^mock_coordinator_cancel)(PaymentRequestCoordinator*); typedef void (^mock_coordinator_complete)(PaymentRequestCoordinator*, - const autofill::CreditCard&, - const base::string16&); + const std::string&, + const std::string&); typedef void (^mock_coordinator_select_shipping_address)( PaymentRequestCoordinator*, const autofill::AutofillProfile&); @@ -59,10 +65,10 @@ } - (void)paymentRequestCoordinator:(PaymentRequestCoordinator*)coordinator - didCompletePaymentRequestWithCard:(const autofill::CreditCard&)card - verificationCode:(const base::string16&)verificationCode { + didReceiveFullMethodName:(const std::string&)methodName + stringifiedDetails:(const std::string&)stringifiedDetails { return static_cast<mock_coordinator_complete>([self blockForSelector:_cmd])( - coordinator, card, verificationCode); + coordinator, methodName, stringifiedDetails); } - (void)paymentRequestCoordinator:(PaymentRequestCoordinator*)coordinator @@ -102,6 +108,8 @@ payment_request_->SetPrefService(pref_service_.get()); } + base::test::ScopedTaskEnvironment scoped_task_evironment_; + autofill::AutofillProfile autofill_profile_; autofill::CreditCard credit_card_; std::unique_ptr<PrefService> pref_service_; @@ -147,7 +155,7 @@ // Tests that calling the FullCardRequesterConsumer delegate method which // notifies the coordinator about successful unmasking of a credit card invokes // the appropriate coordinator delegate method with the expected information. -TEST_F(PaymentRequestCoordinatorTest, FullCardRequestDidSucceed) { +TEST_F(PaymentRequestCoordinatorTest, FullCardRequestDidSucceedWithMethodName) { UIViewController* base_view_controller = [[UIViewController alloc] init]; ScopedKeyWindow scoped_key_window_; [scoped_key_window_.Get() setRootViewController:base_view_controller]; @@ -160,22 +168,38 @@ mockForProtocol:@protocol(PaymentMethodSelectionCoordinatorDelegate)]; id delegate_mock([[PaymentRequestCoordinatorDelegateMock alloc] initWithRepresentedObject:delegate]); - SEL selector = - @selector(paymentRequestCoordinator:didCompletePaymentRequestWithCard - :verificationCode:); + SEL selector = @selector + (paymentRequestCoordinator:didReceiveFullMethodName:stringifiedDetails:); [delegate_mock onSelector:selector callBlockExpectation:^(PaymentRequestCoordinator* callerCoordinator, - const autofill::CreditCard& card, - const base::string16& verificationCode) { - EXPECT_EQ(credit_card_, card); - EXPECT_EQ(base::ASCIIToUTF16("123"), verificationCode); + const std::string& methodName, + const std::string& stringifiedDetails) { + EXPECT_EQ("visa", methodName); + + std::string cvc; + std::unique_ptr<base::DictionaryValue> detailsDict = + base::DictionaryValue::From( + base::JSONReader::Read(stringifiedDetails)); + detailsDict->GetString("cardSecurityCode", &cvc); + EXPECT_EQ("123", cvc); + EXPECT_EQ(coordinator, callerCoordinator); }]; [coordinator setDelegate:delegate_mock]; + std::string methodName = "visa"; + std::string appLocale = ""; + + std::unique_ptr<base::DictionaryValue> response_value = + payments::data_util::GetBasicCardResponseFromAutofillCreditCard( + credit_card_, base::ASCIIToUTF16("123"), autofill_profile_, appLocale) + .ToDictionaryValue(); + std::string stringifiedDetails; + base::JSONWriter::Write(*response_value, &stringifiedDetails); + // Call the card unmasking delegate method. - [coordinator fullCardRequestDidSucceedWithCard:credit_card_ - verificationCode:base::ASCIIToUTF16("123")]; + [coordinator fullCardRequestDidSucceedWithMethodName:methodName + stringifiedDetails:stringifiedDetails]; } // Tests that calling the ShippingAddressSelectionCoordinator delegate method
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm index 1a5be16f..8ca02c5 100644 --- a/ios/chrome/browser/ui/payments/payment_request_manager.mm +++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -8,6 +8,7 @@ #include "base/ios/block_types.h" #include "base/ios/ios_util.h" +#include "base/json/json_reader.h" #import "base/mac/bind_objc_block.h" #include "base/mac/foundation_util.h" #include "base/memory/ptr_util.h" @@ -77,9 +78,8 @@ NSString* kCancelMessage = @"The payment request was canceled."; struct PendingPaymentResponse { - autofill::CreditCard creditCard; - base::string16 verificationCode; - autofill::AutofillProfile billingAddress; + std::string methodName; + std::string stringifiedDetails; autofill::AutofillProfile shippingAddress; autofill::AutofillProfile contactAddress; }; @@ -658,8 +658,13 @@ #pragma mark - PaymentRequestUIDelegate -- (void)openFullCardRequestUI { - [_paymentRequestCoordinator sendPaymentResponse]; +- (void) +requestFullCreditCard:(const autofill::CreditCard&)creditCard + resultDelegate: + (base::WeakPtr<autofill::payments::FullCardRequest::ResultDelegate>) + resultDelegate { + [_paymentRequestCoordinator requestFullCreditCard:creditCard + resultDelegate:resultDelegate]; } #pragma mark - PaymentRequestCoordinatorDelegate methods @@ -683,19 +688,10 @@ } - (void)paymentRequestCoordinator:(PaymentRequestCoordinator*)coordinator - didCompletePaymentRequestWithCard:(const autofill::CreditCard&)card - verificationCode:(const base::string16&)verificationCode { - _pendingPaymentResponse.creditCard = card; - _pendingPaymentResponse.verificationCode = verificationCode; - - DCHECK(!card.billing_address_id().empty()); - autofill::AutofillProfile* billingAddress = - autofill::PersonalDataManager::GetProfileFromProfilesByGUID( - card.billing_address_id(), _paymentRequest->billing_profiles()); - DCHECK(billingAddress); - _pendingPaymentResponse.billingAddress = *billingAddress; - _addressNormalizationManager->StartNormalizingAddress( - &_pendingPaymentResponse.billingAddress); + didReceiveFullMethodName:(const std::string&)methodName + stringifiedDetails:(const std::string&)stringifiedDetails { + _pendingPaymentResponse.methodName = methodName; + _pendingPaymentResponse.stringifiedDetails = stringifiedDetails; if (_paymentRequest->request_shipping()) { // TODO(crbug.com/602666): User should get here only if they have selected @@ -729,24 +725,10 @@ - (void)paymentRequestAddressNormalizationDidComplete { web::PaymentResponse paymentResponse; - // If the merchant specified the card network as part of the "basic-card" - // payment method, return "basic-card" as the method_name. Otherwise, return - // the name of the network directly. - std::string issuer_network = autofill::data_util::GetPaymentRequestData( - _pendingPaymentResponse.creditCard.network()) - .basic_card_issuer_network; paymentResponse.method_name = - _paymentRequest->basic_card_specified_networks().find(issuer_network) != - _paymentRequest->basic_card_specified_networks().end() - ? base::ASCIIToUTF16("basic-card") - : base::ASCIIToUTF16(issuer_network); + base::ASCIIToUTF16(_pendingPaymentResponse.methodName); - paymentResponse.details = - payments::data_util::GetBasicCardResponseFromAutofillCreditCard( - _pendingPaymentResponse.creditCard, - _pendingPaymentResponse.verificationCode, - _pendingPaymentResponse.billingAddress, - GetApplicationContext()->GetApplicationLocale()); + paymentResponse.details = _pendingPaymentResponse.stringifiedDetails; if (_paymentRequest->request_shipping()) { paymentResponse.shipping_address =
diff --git a/ios/chrome/browser/ui/payments/payment_request_mediator.mm b/ios/chrome/browser/ui/payments/payment_request_mediator.mm index e9c2cb6..6add498 100644 --- a/ios/chrome/browser/ui/payments/payment_request_mediator.mm +++ b/ios/chrome/browser/ui/payments/payment_request_mediator.mm
@@ -12,6 +12,7 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/field_types.h" +#include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/currency_formatter.h" #include "components/payments/core/payment_prefs.h" #include "components/payments/core/strings_util.h" @@ -73,7 +74,7 @@ #pragma mark - PaymentRequestViewControllerDataSource - (BOOL)canPay { - return self.paymentRequest->selected_credit_card() != nullptr && + return self.paymentRequest->selected_payment_method() != nullptr && (self.paymentRequest->selected_shipping_option() != nullptr || ![self requestShipping]) && (self.paymentRequest->selected_shipping_profile() != nullptr || @@ -174,7 +175,7 @@ } - (CollectionViewItem*)paymentMethodSectionHeaderItem { - if (!self.paymentRequest->selected_credit_card()) + if (!self.paymentRequest->selected_payment_method()) return nil; PaymentsTextItem* item = [[PaymentsTextItem alloc] init]; item.text = @@ -183,18 +184,13 @@ } - (CollectionViewItem*)paymentMethodItem { - const autofill::CreditCard* creditCard = - self.paymentRequest->selected_credit_card(); - if (creditCard) { + const payments::PaymentInstrument* paymentMethod = + self.paymentRequest->selected_payment_method(); + if (paymentMethod) { PaymentMethodItem* item = [[PaymentMethodItem alloc] init]; - item.methodID = - base::SysUTF16ToNSString(creditCard->NetworkAndLastFourDigits()); - item.methodDetail = base::SysUTF16ToNSString( - creditCard->GetRawInfo(autofill::CREDIT_CARD_NAME_FULL)); - int issuerNetworkIconID = - autofill::data_util::GetPaymentRequestData(creditCard->network()) - .icon_resource_id; - item.methodTypeIcon = NativeImage(issuerNetworkIconID); + item.methodID = base::SysUTF16ToNSString(paymentMethod->GetLabel()); + item.methodDetail = base::SysUTF16ToNSString(paymentMethod->GetSublabel()); + item.methodTypeIcon = NativeImage(paymentMethod->icon_resource_id()); item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; return item; } @@ -202,7 +198,7 @@ CollectionViewDetailItem* item = [[CollectionViewDetailItem alloc] init]; item.text = l10n_util::GetNSString(IDS_PAYMENT_REQUEST_PAYMENT_METHOD_SECTION_NAME); - if (self.paymentRequest->credit_cards().empty()) { + if (self.paymentRequest->payment_methods().empty()) { item.detailText = [l10n_util::GetNSString(IDS_ADD) uppercaseStringWithLocale:[NSLocale currentLocale]]; } else {
diff --git a/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm index ca07b06..ef3e1b2c 100644 --- a/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_mediator_unittest.mm
@@ -14,6 +14,7 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_prefs.h" #include "components/payments/core/payments_test_util.h" #include "components/payments/core/strings_util.h" @@ -89,20 +90,20 @@ // Tests whether payment can be completed when expected. TEST_F(PaymentRequestMediatorTest, TestCanPay) { - EXPECT_TRUE(payment_request_->selected_credit_card()); + EXPECT_TRUE(payment_request_->selected_payment_method()); EXPECT_TRUE(payment_request_->selected_shipping_profile()); EXPECT_TRUE(payment_request_->selected_shipping_option()); EXPECT_TRUE(payment_request_->selected_contact_profile()); EXPECT_TRUE([GetPaymentRequestMediator() canPay]); - // Payment cannot be completed if there is no selected credit card. - autofill::CreditCard* selected_credit_card = - payment_request_->selected_credit_card(); - payment_request_->set_selected_credit_card(nullptr); + // Payment cannot be completed if there is no selected payment method. + payments::PaymentInstrument* selected_payment_method = + payment_request_->selected_payment_method(); + payment_request_->set_selected_payment_method(nullptr); EXPECT_FALSE([GetPaymentRequestMediator() canPay]); - // Restore the selected credit card. - payment_request_->set_selected_credit_card(selected_credit_card); + // Restore the selected payment method. + payment_request_->set_selected_payment_method(selected_payment_method); EXPECT_TRUE([GetPaymentRequestMediator() canPay]); // Payment cannot be completed if there is no selected shipping profile, @@ -308,11 +309,11 @@ EXPECT_EQ(MDCCollectionViewCellAccessoryDisclosureIndicator, payment_method_item.accessoryType); - // Reset the selected credit card. - payment_request_->set_selected_credit_card(nullptr); + // Reset the selected payment method. + payment_request_->set_selected_payment_method(nullptr); - // When there is no selected credit card, the Payment Method item should be of - // type CollectionViewDetailItem. + // When there is no selected payment method, the Payment Method item should be + // of type CollectionViewDetailItem. item = [GetPaymentRequestMediator() paymentMethodItem]; ASSERT_TRUE([item isMemberOfClass:[CollectionViewDetailItem class]]); CollectionViewDetailItem* add_payment_method_item = @@ -324,8 +325,8 @@ EXPECT_EQ(MDCCollectionViewCellAccessoryDisclosureIndicator, add_payment_method_item.accessoryType); - // Remove the credit cards. - payment_request_->ClearCreditCards(); + // Remove the payment methods. + payment_request_->ClearPaymentMethods(); // No accessory view indicates there are no payment methods to choose from. item = [GetPaymentRequestMediator() paymentMethodItem];
diff --git a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm index b9271376..27f5628e 100644 --- a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm
@@ -144,6 +144,7 @@ CollectionViewTextItem* siteHeader = [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; siteHeader.text = l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_SITE); + siteHeader.textColor = [[MDCPalette greyPalette] tint500]; [model setHeader:siteHeader forSectionWithIdentifier:SectionIdentifierSite]; PasswordDetailsItem* siteItem = [[PasswordDetailsItem alloc] initWithType:ItemTypeSite];
diff --git a/ios/chrome/browser/web/progress_indicator_egtest.mm b/ios/chrome/browser/web/progress_indicator_egtest.mm index 5f5daf7..f82a548e 100644 --- a/ios/chrome/browser/web/progress_indicator_egtest.mm +++ b/ios/chrome/browser/web/progress_indicator_egtest.mm
@@ -160,8 +160,7 @@ // Tests that the progress indicator is shown and has expected progress value // after a form is submitted, and the toolbar is visible. -// TODO(crbug.com/734874): Reenable test when fixed. -- (void)DISABLED_testProgressIndicatorShownOnFormSubmit { +- (void)testProgressIndicatorShownOnFormSubmit { if (IsIPadIdiom()) { EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (no progress view in tablet)"); }
diff --git a/ios/web/payments/payment_request.cc b/ios/web/payments/payment_request.cc index 8b6d3b2..7798b25 100644 --- a/ios/web/payments/payment_request.cc +++ b/ios/web/payments/payment_request.cc
@@ -362,7 +362,7 @@ result->SetString(kPaymentRequestId, this->payment_request_id); result->SetString(kPaymentResponseMethodName, this->method_name); - result->Set(kPaymentResponseDetails, this->details.ToDictionaryValue()); + result->SetString(kPaymentResponseDetails, this->details); if (!this->shipping_address.ToDictionaryValue()->empty()) { result->Set(kPaymentResponseShippingAddress, this->shipping_address.ToDictionaryValue());
diff --git a/ios/web/payments/payment_request_unittest.cc b/ios/web/payments/payment_request_unittest.cc index 3aeaee1..c80ccc4 100644 --- a/ios/web/payments/payment_request_unittest.cc +++ b/ios/web/payments/payment_request_unittest.cc
@@ -6,6 +6,7 @@ #include <vector> +#include "base/json/json_writer.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "components/payments/core/basic_card_response.h" @@ -263,9 +264,7 @@ TEST(PaymentRequestTest, EmptyResponseDictionary) { base::DictionaryValue expected_value; - std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue); - details->SetString("cardNumber", ""); - expected_value.Set("details", std::move(details)); + expected_value.SetString("details", ""); expected_value.SetString("paymentRequestID", ""); expected_value.SetString("methodName", ""); @@ -289,7 +288,9 @@ new base::DictionaryValue); billing_address->SetString("postalCode", "90210"); details->Set("billingAddress", std::move(billing_address)); - expected_value.Set("details", std::move(details)); + std::string stringified_details; + base::JSONWriter::Write(*details, &stringified_details); + expected_value.SetString("details", stringified_details); expected_value.SetString("paymentRequestID", "12345"); expected_value.SetString("methodName", "American Express"); std::unique_ptr<base::DictionaryValue> shipping_address( @@ -304,14 +305,23 @@ PaymentResponse payment_response; payment_response.payment_request_id = base::ASCIIToUTF16("12345"); payment_response.method_name = base::ASCIIToUTF16("American Express"); - payment_response.details.card_number = + + payments::BasicCardResponse payment_response_details; + payment_response_details.card_number = base::ASCIIToUTF16("1111-1111-1111-1111"); - payment_response.details.cardholder_name = base::ASCIIToUTF16("Jon Doe"); - payment_response.details.expiry_month = base::ASCIIToUTF16("02"); - payment_response.details.expiry_year = base::ASCIIToUTF16("2090"); - payment_response.details.card_security_code = base::ASCIIToUTF16("111"); - payment_response.details.billing_address.postal_code = + payment_response_details.cardholder_name = base::ASCIIToUTF16("Jon Doe"); + payment_response_details.expiry_month = base::ASCIIToUTF16("02"); + payment_response_details.expiry_year = base::ASCIIToUTF16("2090"); + payment_response_details.card_security_code = base::ASCIIToUTF16("111"); + payment_response_details.billing_address.postal_code = base::ASCIIToUTF16("90210"); + std::unique_ptr<base::DictionaryValue> response_value = + payment_response_details.ToDictionaryValue(); + std::string payment_response_stringified_details; + base::JSONWriter::Write(*response_value, + &payment_response_stringified_details); + payment_response.details = payment_response_stringified_details; + payment_response.shipping_address.postal_code = base::ASCIIToUTF16("94115"); payment_response.shipping_option = base::ASCIIToUTF16("666"); payment_response.payer_name = base::ASCIIToUTF16("Jane Doe"); @@ -630,13 +640,21 @@ payments::BasicCardResponse card_response1; card_response1.card_number = base::ASCIIToUTF16("1234"); + std::unique_ptr<base::DictionaryValue> response_value1 = + card_response1.ToDictionaryValue(); + std::string stringified_card_response1; + base::JSONWriter::Write(*response_value1, &stringified_card_response1); payments::BasicCardResponse card_response2; card_response2.card_number = base::ASCIIToUTF16("8888"); - response1.details = card_response1; + std::unique_ptr<base::DictionaryValue> response_value2 = + card_response2.ToDictionaryValue(); + std::string stringified_card_response2; + base::JSONWriter::Write(*response_value2, &stringified_card_response2); + response1.details = stringified_card_response1; EXPECT_NE(response1, response2); - response2.details = card_response2; + response2.details = stringified_card_response2; EXPECT_NE(response1, response2); - response2.details = card_response1; + response2.details = stringified_card_response1; EXPECT_EQ(response1, response2); }
diff --git a/ios/web/public/payments/payment_request.h b/ios/web/public/payments/payment_request.h index 4452690..76e80fe2 100644 --- a/ios/web/public/payments/payment_request.h +++ b/ios/web/public/payments/payment_request.h
@@ -264,7 +264,7 @@ // A credit card response object used by the merchant to process the // transaction and determine successful fund transfer. - payments::BasicCardResponse details; + std::string details; // If request_shipping was set to true in the PaymentOptions passed to the // PaymentRequest constructor, this will be the full and final shipping
diff --git a/ipc/README.md b/ipc/README.md index 2b1f9f2..be5624d 100644 --- a/ipc/README.md +++ b/ipc/README.md
@@ -604,7 +604,7 @@ to define the mapping: ``` -mojom = "//content/common/url_loader.mojom" +mojom = "//content/public/common/url_loader.mojom" public_headers = [ "//content/common/resource_request.h" ] traits_headers = [ "//content/common/resource_messages.h" ] ...
diff --git a/media/capture/video_capturer_source.cc b/media/capture/video_capturer_source.cc index 7ff9915..bafdf42 100644 --- a/media/capture/video_capturer_source.cc +++ b/media/capture/video_capturer_source.cc
@@ -13,12 +13,4 @@ // to generate symbols across linking units. VideoCapturerSource::~VideoCapturerSource() {} -void VideoCapturerSource::GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback) { - callback.Run(GetPreferredFormats()); -} - } // namespace media
diff --git a/media/capture/video_capturer_source.h b/media/capture/video_capturer_source.h index 2cb9c02..c4cc854 100644 --- a/media/capture/video_capturer_source.h +++ b/media/capture/video_capturer_source.h
@@ -50,18 +50,6 @@ using RunningCallback = base::Callback<void(bool)>; - // Collects the formats that can currently be used. - // |max_requested_height|, |max_requested_width|, and - // |max_requested_frame_rate| is used by Tab and Screen capture to decide what - // resolution/framerate to generate. |callback| is triggered when the formats - // have been collected. - // TODO(guidou): Remove this method. http://crbug.com/706408 - virtual void GetCurrentSupportedFormats( - int max_requested_width, - int max_requested_height, - double max_requested_frame_rate, - const VideoCaptureDeviceFormatsCB& callback); - // Returns formats that are preferred and can currently be used. May be empty // if no formats are available or known. virtual VideoCaptureFormats GetPreferredFormats() = 0;
diff --git a/media/filters/frame_processor.cc b/media/filters/frame_processor.cc index 6bb03a0..41d79c8 100644 --- a/media/filters/frame_processor.cc +++ b/media/filters/frame_processor.cc
@@ -58,6 +58,10 @@ needs_random_access_point_ = needs_random_access_point; } + DecodeTimestamp last_processed_decode_timestamp() const { + return last_processed_decode_timestamp_; + } + // Gets a pointer to this track's ChunkDemuxerStream. ChunkDemuxerStream* stream() const { return stream_; } @@ -82,11 +86,24 @@ // |processed_frames_| is cleared in both cases. bool FlushProcessedFrames(); + // Signals this track buffer's stream that a coded frame group is starting + // with decode timestamp |start_timestamp|. + void NotifyStartOfCodedFrameGroup(DecodeTimestamp start_time); + private: // The decode timestamp of the last coded frame appended in the current coded // frame group. Initially kNoTimestamp, meaning "unset". DecodeTimestamp last_decode_timestamp_; + // On signalling the stream of a new coded frame group start time, this is + // reset to that start time. Any buffers subsequently enqueued for emission to + // the stream update this. This is managed separately from + // |last_decode_timestamp_| because |last_processed_decode_timestamp_| is not + // reset during Reset(), to especially be able to track the need to signal + // coded frame group start time for muxed post-discontiuity edge cases. See + // also FrameProcessor::ProcessFrame(). + DecodeTimestamp last_processed_decode_timestamp_; + // The coded frame duration of the last coded frame appended in the current // coded frame group. Initially kNoTimestamp, meaning "unset". base::TimeDelta last_frame_duration_; @@ -116,6 +133,7 @@ MseTrackBuffer::MseTrackBuffer(ChunkDemuxerStream* stream) : last_decode_timestamp_(kNoDecodeTimestamp()), + last_processed_decode_timestamp_(DecodeTimestamp()), last_frame_duration_(kNoTimestamp), highest_presentation_timestamp_(kNoTimestamp), needs_random_access_point_(true), @@ -146,6 +164,7 @@ void MseTrackBuffer::EnqueueProcessedFrame( const scoped_refptr<StreamParserBuffer>& frame) { + last_processed_decode_timestamp_ = frame->GetDecodeTimestamp(); processed_frames_.push_back(frame); } @@ -162,6 +181,11 @@ return result; } +void MseTrackBuffer::NotifyStartOfCodedFrameGroup(DecodeTimestamp start_time) { + last_processed_decode_timestamp_ = start_time; + stream_->OnStartOfCodedFrameGroup(start_time); +} + FrameProcessor::FrameProcessor(const UpdateDurationCB& update_duration_cb, MediaLog* media_log) : group_start_timestamp_(kNoTimestamp), @@ -188,7 +212,7 @@ } else if (sequence_mode_) { // We're switching from 'sequence' to 'segments' mode. Be safe and signal a // new coded frame group on the next frame emitted. - coded_frame_group_last_dts_ = kNoDecodeTimestamp(); + pending_notify_all_group_start_ = true; } // Step 8: Update the attribute to new mode. @@ -314,13 +338,13 @@ itr->second->Reset(); } - // Maintain current |coded_frame_group_last_dts_| state for Reset() during + // Maintain current |pending_notify_all_group_start_| state for Reset() during // sequence mode. Reset it here only if in segments mode. In sequence mode, // the current coded frame group may be continued across Reset() operations to // allow the stream to coalesce what might otherwise be gaps in the buffered - // ranges. See also the declaration for |coded_frame_group_last_dts_|. + // ranges. See also the declaration for |pending_notify_all_group_start_|. if (!sequence_mode_) { - coded_frame_group_last_dts_ = kNoDecodeTimestamp(); + pending_notify_all_group_start_ = true; return; } @@ -357,7 +381,7 @@ DVLOG(2) << __func__ << "(" << start_timestamp.InSecondsF() << ")"; for (auto itr = track_buffers_.begin(); itr != track_buffers_.end(); ++itr) { - itr->second->stream()->OnStartOfCodedFrameGroup(start_timestamp); + itr->second->NotifyStartOfCodedFrameGroup(start_timestamp); } } @@ -610,7 +634,7 @@ decode_timestamp - track_last_decode_timestamp; if (track_dts_delta < base::TimeDelta() || track_dts_delta > 2 * track_buffer->last_frame_duration()) { - DCHECK(coded_frame_group_last_dts_ != kNoDecodeTimestamp()); + DCHECK(!pending_notify_all_group_start_); // 6.1. If mode equals "segments": Set group end timestamp to // presentation timestamp. // If mode equals "sequence": Set group start timestamp equal to @@ -619,8 +643,8 @@ group_end_timestamp_ = presentation_timestamp; // This triggers a discontinuity so we need to treat the next frames // appended within the append window as if they were the beginning of - // a new coded frame group. |coded_frame_group_last_dts_| is reset in - // Reset(), below, for "segments" mode. + // a new coded frame group. |pending_notify_all_group_start_| is reset + // in Reset(), below, for "segments" mode. } else { DVLOG(3) << __func__ << " : Sequence mode discontinuity, GETS: " << group_end_timestamp_.InSecondsF(); @@ -711,33 +735,43 @@ // We now have a processed buffer to append to the track buffer's stream. // If it is the first in a new coded frame group (such as following a - // discontinuity), notify all the track buffers' streams that a coded frame - // group is starting. - // If in 'sequence' appendMode, also check to make sure we don't need to - // signal the start of a new coded frame group in the case where - // timestampOffset adjustments by the app may cause this coded frame to be - // in the timeline prior to the last frame processed. - if (coded_frame_group_last_dts_ == kNoDecodeTimestamp() || - (sequence_mode_ && coded_frame_group_last_dts_ > decode_timestamp)) { + // segments append mode discontinuity, or following a switch to segments + // append mode from sequence append mode), notify all the track buffers + // that a coded frame group is starting. + // + // Otherwise, if the buffer's DTS indicates that a new coded frame group + // needs signalling, signal just the buffer's track buffer. This can + // happen in both sequence and segments append modes when the first + // processed track's frame following a discontinuity has a higher DTS than + // this later processed track's first frame following that discontinuity. + if (pending_notify_all_group_start_ || + track_buffer->last_processed_decode_timestamp() > decode_timestamp) { + DCHECK(frame->is_key_frame()); + // First, complete the append to track buffer streams of the previous // coded frame group's frames, if any. if (!FlushProcessedFrames()) return false; - // TODO(wolenetz): This should be changed to a presentation timestamp. See - // http://crbug.com/402502 - NotifyStartOfCodedFrameGroup(decode_timestamp); + if (pending_notify_all_group_start_) { + // TODO(wolenetz): This should be changed to a presentation timestamp. + // See http://crbug.com/402502 + NotifyStartOfCodedFrameGroup(decode_timestamp); + pending_notify_all_group_start_ = false; + } else { + // TODO(wolenetz): This should be changed to a presentation timestamp. + // See http://crbug.com/402502 + track_buffer->NotifyStartOfCodedFrameGroup(decode_timestamp); + } } - coded_frame_group_last_dts_ = decode_timestamp; - DVLOG(3) << __func__ << ": Sending processed frame to stream, " << "PTS=" << presentation_timestamp.InSecondsF() << ", DTS=" << decode_timestamp.InSecondsF(); // Steps 11-16: Note, we optimize by appending groups of contiguous // processed frames for each track buffer at end of ProcessFrames() or prior - // to NotifyStartOfCodedFrameGroup(). + // to signalling coded frame group starts. track_buffer->EnqueueProcessedFrame(frame); // 17. Set last decode timestamp for track buffer to decode timestamp.
diff --git a/media/filters/frame_processor.h b/media/filters/frame_processor.h index cd8d662..2a7d33d 100644 --- a/media/filters/frame_processor.h +++ b/media/filters/frame_processor.h
@@ -145,17 +145,14 @@ // set to false ("segments"). bool sequence_mode_ = false; - // Tracks whether or not the next processed frame is a continuation of a coded - // frame group (see https://w3c.github.io/media-source/#coded-frame-group). - // Resets to kNoDecodeTimestamp() upon detection of 'segments' mode - // discontinuity, parser reset during 'segments' mode, or switching from - // 'sequence' to 'segments' mode. - // Once a processed coded frame is emitted for the current coded frame group, - // tracks the decode timestamp of the last frame emitted. - // Explicit setting of timestampOffset will trigger subsequent notification of - // a new coded frame start to the tracks' streams, even in 'sequence' mode, if - // the resulting frame has a DTS less than this. - DecodeTimestamp coded_frame_group_last_dts_ = kNoDecodeTimestamp(); + // Tracks whether or not we need to notify all track buffers of a new coded + // frame group (see https://w3c.github.io/media-source/#coded-frame-group) + // upon the next successfully processed frame. Set true initially and upon + // detection of 'segments' mode discontinuity, parser reset during 'segments' + // mode, or switching from 'sequence' to 'segments' mode. Individual track + // buffers can also be notified of an updated coded frame group start in edge + // cases. See further comments in ProcessFrame(). + bool pending_notify_all_group_start_ = true; // Tracks the MSE coded frame processing variable of same name. // Initially kNoTimestamp, meaning "unset".
diff --git a/media/filters/frame_processor_unittest.cc b/media/filters/frame_processor_unittest.cc index 679a6f4..7c5fb88 100644 --- a/media/filters/frame_processor_unittest.cc +++ b/media/filters/frame_processor_unittest.cc
@@ -253,8 +253,7 @@ // thereof of new coded frame group by the FrameProcessor. See // https://crbug.com/580613. bool in_coded_frame_group() { - return frame_processor_->coded_frame_group_last_dts_ != - kNoDecodeTimestamp(); + return !frame_processor_->pending_notify_all_group_start_; } void seek(ChunkDemuxerStream* stream, base::TimeDelta seek_time) { @@ -652,7 +651,15 @@ // This causes [55,85) to merge with [100,230) here for audio, and similar // for video. See also https://crbug.com/620523. CheckExpectedRangesByTimestamp(audio_.get(), "{ [55,230) }"); - CheckExpectedRangesByTimestamp(video_.get(), "{ [55,240) }"); + // Note that 'sequence' mode group start signalling (if the decode time goes + // into the past) is per-track after the first frame has been processed. + // Hence 65, not 55 here. Similarly, 'segments' mode muxed tracks where + // discontinuity is followed by tracks whose first frames decrease in DTS + // relative to each other (allowed since media segments are not required to + // contain frames for every track) could result in decreasing range start + // times for those later tracks. See + // AudioVideo_OutOfSequence_After_Discontinuity for deeper verification. + CheckExpectedRangesByTimestamp(video_.get(), "{ [65,240) }"); } else { CheckExpectedRangesByTimestamp(audio_.get(), "{ [55,85) [100,130) [200,230) }"); @@ -691,6 +698,124 @@ } } +TEST_P(FrameProcessorTest, AudioVideo_OutOfSequence_After_Discontinuity) { + // Once a discontinuity is detected (and all tracks drop everything until the + // next keyframe per each track), we should gracefully handle the case where + // some tracks' first keyframe after the discontinuity are appended after, but + // end up earlier in timeline than some other track(s). In particular, we + // shouldn't notify all tracks that a new coded frame group is starting and + // begin dropping leading non-keyframes from all tracks. Rather, we should + // notify just the track encountering this new type of discontinuity. Since + // MSE doesn't require all media segments to contain media from every track, + // these append sequences can occur. + InSequence s; + AddTestTracks(HAS_AUDIO | HAS_VIDEO); + bool using_sequence_mode = GetParam(); + frame_processor_->SetSequenceMode(using_sequence_mode); + + // Begin with a simple set of appends for all tracks. + if (using_sequence_mode) { + // Allow room in the timeline for the last audio append (50K, below) in this + // test to remain within default append window [0, +Infinity]. Moving the + // sequence mode appends to begin at time 100ms, the same time as the first + // append, below, results in a -20ms offset (instead of a -120ms offset) + // applied to frames beginning at the first frame after the discontinuity + // caused by the video append at 160K, below. + SetTimestampOffset(frame_duration_ * 10); + } + EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_ * 14)); + ProcessFrames("100K 110K 120K", "110K 120K 130K"); + EXPECT_TRUE(in_coded_frame_group()); + EXPECT_EQ(base::TimeDelta(), timestamp_offset_); + CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }"); + CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) }"); + + // Trigger (normal) discontinuity with one track (video). + if (using_sequence_mode) + EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_ * 15)); + else + EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_ * 17)); + + ProcessFrames("", "160K"); + EXPECT_TRUE(in_coded_frame_group()); + + if (using_sequence_mode) { + // The new video buffer is relocated into [140,150). + EXPECT_EQ(frame_duration_ * -2, timestamp_offset_); + CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }"); + CheckExpectedRangesByTimestamp(video_.get(), "{ [100,150) }"); + } else { + // The new video buffer is at [160,170). + EXPECT_EQ(base::TimeDelta(), timestamp_offset_); + CheckExpectedRangesByTimestamp(audio_.get(), "{ [100,130) }"); + CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [160,170) }"); + } + + // Append to the other track (audio) with lower time than the video frame we + // just appended. Append with a timestamp such that segments mode demonstrates + // we don't retroactively extend the new video buffer appended above's range + // start back to this audio start time. + if (using_sequence_mode) + EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_ * 15)); + else + EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_ * 17)); + + ProcessFrames("50K", ""); + EXPECT_TRUE(in_coded_frame_group()); + + // Because this is the first audio buffer appended following the discontinuity + // detected while appending the video frame, above, a new coded frame group + // for video is not triggered. + if (using_sequence_mode) { + // The new audio buffer is relocated into [30,40). Note the muxed 'sequence' + // mode append mode results in a buffered range gap in this case. + EXPECT_EQ(frame_duration_ * -2, timestamp_offset_); + CheckExpectedRangesByTimestamp(audio_.get(), "{ [30,40) [100,130) }"); + CheckExpectedRangesByTimestamp(video_.get(), "{ [100,150) }"); + } else { + EXPECT_EQ(base::TimeDelta(), timestamp_offset_); + CheckExpectedRangesByTimestamp(audio_.get(), "{ [50,60) [100,130) }"); + CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [160,170) }"); + } + + // Finally, append a non-keyframe to the first track (video), to continue the + // GOP that started the normal discontinuity on the previous video append. + if (using_sequence_mode) + EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_ * 16)); + else + EXPECT_CALL(callbacks_, PossibleDurationIncrease(frame_duration_ * 18)); + + ProcessFrames("", "170"); + EXPECT_TRUE(in_coded_frame_group()); + + // Verify the final buffers. First, re-seek audio since we appended data + // earlier than what already satisfied our initial seek to start. We satisfy + // the seek with the first buffer in [0,1000). + seek(audio_.get(), base::TimeDelta()); + if (using_sequence_mode) { + // The new video buffer is relocated into [150,160). + EXPECT_EQ(frame_duration_ * -2, timestamp_offset_); + CheckExpectedRangesByTimestamp(audio_.get(), "{ [30,40) [100,130) }"); + CheckReadsThenReadStalls(audio_.get(), "30:50"); + seek(audio_.get(), 10 * frame_duration_); + CheckReadsThenReadStalls(audio_.get(), "100 110 120"); + + CheckExpectedRangesByTimestamp(video_.get(), "{ [100,160) }"); + CheckReadsThenReadStalls(video_.get(), "110 120 130 140:160 150:170"); + } else { + EXPECT_EQ(base::TimeDelta(), timestamp_offset_); + CheckExpectedRangesByTimestamp(audio_.get(), "{ [50,60) [100,130) }"); + CheckReadsThenReadStalls(audio_.get(), "50"); + seek(audio_.get(), 10 * frame_duration_); + CheckReadsThenReadStalls(audio_.get(), "100 110 120"); + + CheckExpectedRangesByTimestamp(video_.get(), "{ [100,140) [160,180) }"); + CheckReadsThenReadStalls(video_.get(), "110 120 130"); + seek(video_.get(), 16 * frame_duration_); + CheckReadsThenReadStalls(video_.get(), "160 170"); + } +} + TEST_P(FrameProcessorTest, AppendWindowFilterOfNegativeBufferTimestampsWithPrerollDiscard) { InSequence s;
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index c0316253..5c13b47 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -766,8 +766,7 @@ bool private_network_request = nqe::internal::IsPrivateHost( request.context()->host_resolver(), - HostPortPair(request.url().host(), request.url().EffectiveIntPort()), - net_log_); + HostPortPair(request.url().host(), request.url().EffectiveIntPort())); return (use_localhost_requests_ || !private_network_request) && // Verify that response headers are received, so it can be ensured that
diff --git a/net/nqe/network_quality_estimator_util.cc b/net/nqe/network_quality_estimator_util.cc index bffaac2..34e6b77e 100644 --- a/net/nqe/network_quality_estimator_util.cc +++ b/net/nqe/network_quality_estimator_util.cc
@@ -10,6 +10,7 @@ #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/dns/host_resolver.h" +#include "net/log/net_log_with_source.h" namespace net { @@ -18,14 +19,14 @@ namespace internal { bool IsPrivateHost(HostResolver* host_resolver, - const HostPortPair& host_port_pair, - const NetLogWithSource& net_log) { + const HostPortPair& host_port_pair) { // Try resolving |host_port_pair.host()| synchronously. HostResolver::RequestInfo resolve_info(host_port_pair); resolve_info.set_allow_cached_response(true); AddressList addresses; // Resolve synchronously using the resolver's cache. - int rv = host_resolver->ResolveFromCache(resolve_info, &addresses, net_log); + int rv = host_resolver->ResolveFromCache(resolve_info, &addresses, + NetLogWithSource()); DCHECK_NE(rv, ERR_IO_PENDING); if (rv == OK && !addresses.empty()) {
diff --git a/net/nqe/network_quality_estimator_util.h b/net/nqe/network_quality_estimator_util.h index 94289c1e..02448241 100644 --- a/net/nqe/network_quality_estimator_util.h +++ b/net/nqe/network_quality_estimator_util.h
@@ -11,7 +11,6 @@ class HostPortPair; class HostResolver; -class NetLogWithSource; namespace nqe { @@ -28,8 +27,7 @@ // |host_port_pair|. The method is synchronous. // |host_resolver| must not be null. NET_EXPORT_PRIVATE bool IsPrivateHost(HostResolver* host_resolver, - const HostPortPair& host_port_pair, - const NetLogWithSource& net_log); + const HostPortPair& host_port_pair); } // namespace internal
diff --git a/net/nqe/network_quality_estimator_util_unittest.cc b/net/nqe/network_quality_estimator_util_unittest.cc index 0f80d78..896ac7b7 100644 --- a/net/nqe/network_quality_estimator_util_unittest.cc +++ b/net/nqe/network_quality_estimator_util_unittest.cc
@@ -29,8 +29,6 @@ TEST(NetworkQualityEstimatorUtilTest, ReservedHost) { std::unique_ptr<BoundTestNetLog> net_log = base::MakeUnique<BoundTestNetLog>(); - BoundTestNetLog* net_log_ptr = net_log.get(); - MockCachingHostResolver mock_host_resolver; scoped_refptr<net::RuleBasedHostResolverProc> rules( @@ -75,28 +73,23 @@ EXPECT_EQ(2u, mock_host_resolver.num_resolve()); EXPECT_FALSE(IsPrivateHost(&mock_host_resolver, - HostPortPair("2607:f8b0:4006:819::200e", 80), - net_log_ptr->bound())); + HostPortPair("2607:f8b0:4006:819::200e", 80))); EXPECT_EQ(1u, mock_host_resolver.num_resolve_from_cache()); - EXPECT_TRUE(IsPrivateHost(&mock_host_resolver, - HostPortPair("192.168.0.1", 443), - net_log_ptr->bound())); + EXPECT_TRUE( + IsPrivateHost(&mock_host_resolver, HostPortPair("192.168.0.1", 443))); EXPECT_EQ(2u, mock_host_resolver.num_resolve_from_cache()); - EXPECT_FALSE(IsPrivateHost(&mock_host_resolver, - HostPortPair("92.168.0.1", 443), - net_log_ptr->bound())); + EXPECT_FALSE( + IsPrivateHost(&mock_host_resolver, HostPortPair("92.168.0.1", 443))); EXPECT_EQ(3u, mock_host_resolver.num_resolve_from_cache()); - EXPECT_TRUE(IsPrivateHost(&mock_host_resolver, - HostPortPair("example1.com", 443), - net_log_ptr->bound())); + EXPECT_TRUE( + IsPrivateHost(&mock_host_resolver, HostPortPair("example1.com", 443))); EXPECT_EQ(4u, mock_host_resolver.num_resolve_from_cache()); - EXPECT_FALSE(IsPrivateHost(&mock_host_resolver, - HostPortPair("example2.com", 443), - net_log_ptr->bound())); + EXPECT_FALSE( + IsPrivateHost(&mock_host_resolver, HostPortPair("example2.com", 443))); EXPECT_EQ(5u, mock_host_resolver.num_resolve_from_cache()); // IsPrivateHost() should have queried only the resolver's cache. @@ -109,8 +102,6 @@ TEST(NetworkQualityEstimatorUtilTest, ReservedHostUncached) { std::unique_ptr<BoundTestNetLog> net_log = base::MakeUnique<BoundTestNetLog>(); - BoundTestNetLog* net_log_ptr = net_log.get(); - MockCachingHostResolver mock_host_resolver; scoped_refptr<net::RuleBasedHostResolverProc> rules( @@ -121,9 +112,8 @@ mock_host_resolver.set_rules(rules.get()); // Not in DNS host cache, so should not be marked as private. - EXPECT_FALSE(IsPrivateHost(&mock_host_resolver, - HostPortPair("example3.com", 443), - net_log_ptr->bound())); + EXPECT_FALSE( + IsPrivateHost(&mock_host_resolver, HostPortPair("example3.com", 443))); EXPECT_EQ(0u, mock_host_resolver.num_resolve()); EXPECT_EQ(1u, mock_host_resolver.num_resolve_from_cache()); @@ -140,9 +130,8 @@ EXPECT_EQ(OK, callback.WaitForResult()); EXPECT_EQ(1u, mock_host_resolver.num_resolve()); } - EXPECT_TRUE(IsPrivateHost(&mock_host_resolver, - HostPortPair("example3.com", 443), - net_log_ptr->bound())); + EXPECT_TRUE( + IsPrivateHost(&mock_host_resolver, HostPortPair("example3.com", 443))); // IsPrivateHost() should have queried only the resolver's cache. EXPECT_EQ(1u, mock_host_resolver.num_resolve()); @@ -163,18 +152,12 @@ scoped_refptr<net::RuleBasedHostResolverProc> rules( new net::RuleBasedHostResolverProc(nullptr)); - EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("localhost", 443), - net_log_ptr->bound())); - EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("localhost6", 443), - net_log_ptr->bound())); - EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("127.0.0.1", 80), - net_log_ptr->bound())); - EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("0.0.0.0", 80), - net_log_ptr->bound())); - EXPECT_TRUE( - IsPrivateHost(&resolver, HostPortPair("::1", 80), net_log_ptr->bound())); - EXPECT_FALSE(IsPrivateHost(&resolver, HostPortPair("google.com", 80), - net_log_ptr->bound())); + EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("localhost", 443))); + EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("localhost6", 443))); + EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("127.0.0.1", 80))); + EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("0.0.0.0", 80))); + EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("::1", 80))); + EXPECT_FALSE(IsPrivateHost(&resolver, HostPortPair("google.com", 80))); } } // namespace
diff --git a/net/nqe/throughput_analyzer.cc b/net/nqe/throughput_analyzer.cc index 2c4d1b8..96880ed 100644 --- a/net/nqe/throughput_analyzer.cc +++ b/net/nqe/throughput_analyzer.cc
@@ -263,8 +263,7 @@ bool private_network_request = nqe::internal::IsPrivateHost( request.context()->host_resolver(), - HostPortPair(request.url().host(), request.url().EffectiveIntPort()), - net_log_); + HostPortPair(request.url().host(), request.url().EffectiveIntPort())); return !(use_localhost_requests_for_tests_ || !private_network_request) || request.creation_time() < last_connection_change_;
diff --git a/net/nqe/throughput_analyzer_unittest.cc b/net/nqe/throughput_analyzer_unittest.cc index ca7091f..d3011cd 100644 --- a/net/nqe/throughput_analyzer_unittest.cc +++ b/net/nqe/throughput_analyzer_unittest.cc
@@ -119,11 +119,11 @@ ? "http://127.0.0.1/test.html" : "http://example.com/test.html"; - EXPECT_EQ(test.use_local_requests, - nqe::internal::IsPrivateHost( - context.host_resolver(), - HostPortPair(GURL(url).host(), GURL(url).EffectiveIntPort()), - base::MakeUnique<BoundTestNetLog>()->bound())); + EXPECT_EQ( + test.use_local_requests, + nqe::internal::IsPrivateHost( + context.host_resolver(), + HostPortPair(GURL(url).host(), GURL(url).EffectiveIntPort()))); for (size_t i = 0; i < 1000; ++i) { std::unique_ptr<URLRequest> request( context.CreateRequest(GURL(url), DEFAULT_PRIORITY, &test_delegate,
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc index 68b37d9..dc91c20 100644 --- a/net/quic/core/congestion_control/bbr_sender_test.cc +++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -314,7 +314,6 @@ sender_->ExportDebugState().max_bandwidth); // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures // bandwidth higher than the link rate. - EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); // The margin here is high, because the aggregation greatly increases // smoothed rtt. EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt()); @@ -378,11 +377,10 @@ sender_->ExportDebugState().max_bandwidth); // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures // bandwidth higher than the link rate. - EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); // The margin here is high, because the aggregation greatly increases // smoothed rtt. EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt()); - ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.12f); + ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.33f); } // Test a simple long data transfer with 2 rtts of aggregation.
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 967b5bd..78405b7 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -1601,6 +1601,48 @@ } ] }, + "Android WebView L (dbg)": { + "cts_tests": [ + { + "arch": "arm64", + "platform": "L" + } + ], + "instrumentation_tests": [ + { + "test": "system_webview_shell_layout_test_apk" + } + ] + }, + "Android WebView M (dbg)": { + "cts_tests": [ + { + "arch": "arm64", + "platform": "M" + } + ], + "instrumentation_tests": [ + { + "test": "system_webview_shell_layout_test_apk" + }, + { + "test": "webview_ui_test_app_test_apk" + } + ] + }, + "Android WebView N (dbg)": { + "cts_tests": [ + { + "arch": "arm64", + "platform": "N" + } + ], + "instrumentation_tests": [ + { + "test": "system_webview_shell_layout_test_apk" + } + ] + }, "Android arm Builder (dbg)": { "additional_compile_targets": [ "dump_syms",
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index 37c9525..8285dec5 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -150,6 +150,7 @@ -WebContentsImplBrowserTest.GetSizeForNewRenderView -WebContentsImplBrowserTest.UserAgentOverride -WebContentsViewAuraTest.ScreenshotForSwappedOutRenderViews +-WebRtcGetUserMediaOldConstraintsBrowserTest.GetUserMediaWithInvalidMandatorySourceID -WebRtcGetUserMediaOldConstraintsBrowserTest.TwoGetUserMediaWithFirstHdSecondVga -WebRtcGetUserMediaOldConstraintsBrowserTest.TwoGetUserMediaWithSecondVideoCropped -WebRtcVideoCaptureBrowserTest.RecoverFromCrashInVideoCaptureProcess
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9c3385a..83c4156 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -403,6 +403,25 @@ ] } ], + "CaptivePortalCertificateList": [ + { + "platforms": [ + "android", + "chromeos", + "linux", + "mac", + "win" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "CaptivePortalCertificateList" + ] + } + ] + } + ], "CaptivePortalInterstitial": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 82f6d37..517751a2 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -16369,8 +16369,8 @@ crbug.com/591099 inspector-protocol/css/cssom-matching-rules.html [ Failure ] crbug.com/591099 inspector-protocol/css/cssom-modify-rule-and-get-rule-list.html [ Failure ] crbug.com/591099 inspector-protocol/css/media-query-listener-exception.html [ Failure ] -crbug.com/591099 inspector-protocol/debugger/debugger-step-into-dedicated-worker.html [ Failure ] -crbug.com/591099 inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.html [ Failure ] +crbug.com/591099 inspector-protocol/debugger/debugger-step-into-dedicated-worker.js [ Failure ] +crbug.com/591099 inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js [ Failure ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Crash Failure Timeout ] crbug.com/591099 inspector-protocol/emulation/device-emulation-small-dw.js [ Failure ] crbug.com/591099 inspector-protocol/emulation/device-emulation-small.js [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index 17e0c13..344378c 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -384,6 +384,7 @@ Bug(none) external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html [ Failure Timeout ] Bug(none) external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub.html [ Failure Timeout ] Bug(none) external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub.html [ Failure Timeout ] +Bug(none) external/wpt/html/browsers/offline/appcache/workers/appcache-worker.html [ Timeout ] Bug(none) external/wpt/html/browsers/offline/application-cache-api/api_status_idle.html [ Failure Timeout ] Bug(none) external/wpt/html/browsers/the-window-object/Window-document.html [ Failure Timeout ] Bug(none) external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html [ Failure Timeout ] @@ -2448,7 +2449,7 @@ Bug(none) http/tests/security/media-element-audio-source-node-cross-origin-allowed.html [ Timeout ] Bug(none) http/tests/security/media-element-audio-source-node-cross-origin-with-credentials.html [ Failure Timeout ] Bug(none) http/tests/security/media-element-audio-source-node-cross-origin.html [ Timeout ] -Bug(none) http/tests/security/media-element-audio-source-node-same-origin.html [ Timeout ] +Bug(none) http/tests/security/media-element-audio-source-node-same-origin.html [ Failure Pass ] Bug(none) http/tests/security/mime-type-execute-as-html-01.html [ Failure ] Bug(none) http/tests/security/mime-type-execute-as-html-04.html [ Failure ] Bug(none) http/tests/security/mixedContent/about-blank-iframe-in-main-frame.html [ Timeout ] @@ -3357,3 +3358,4 @@ Bug(none) webshare/share-nonutf8-encoding.html [ Timeout ] Bug(none) webshare/share-success.html [ Timeout ] Bug(none) webshare/share-types.html [ Timeout ] +Bug(none) webshare/share-url-relative.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index 89e2d00d..d68e0905 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -268,7 +268,7 @@ crbug.com/480769 virtual/mojo-loading/http/tests/inspector/service-workers/service-workers-redundant.html [ Slow ] crbug.com/480769 http/tests/inspector/service-workers/service-worker-agents.html [ Slow ] crbug.com/480769 virtual/mojo-loading/http/tests/inspector/service-workers/service-worker-agents.html [ Slow ] -crbug.com/504703 inspector-protocol/debugger/debugger-step-into-dedicated-worker.html [ Slow ] +crbug.com/504703 inspector-protocol/debugger/debugger-step-into-dedicated-worker.js [ Slow ] crbug.com/535478 [ Win ] virtual/threaded/inspector/tracing/decode-resize.html [ Slow ] crbug.com/548765 http/tests/inspector/console-fetch-logging.html [ Slow ] crbug.com/548765 virtual/mojo-loading/http/tests/inspector/console-fetch-logging.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 0fd4cfe1..9600407 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -402,7 +402,7 @@ crbug.com/636993 virtual/layout_ng/external/wpt/css/CSS2/linebox/vertical-align-sub-001.xht [ Failure ] crbug.com/636993 virtual/layout_ng/external/wpt/css/CSS2/linebox/vertical-align-super-001.xht [ Failure ] -# Atomic inline margins. +# Inline: abspos inline static positions. crbug.com/636993 virtual/layout_ng/external/wpt/css/CSS2/linebox/vertical-align-baseline-004a.xht [ Failure ] crbug.com/636993 virtual/layout_ng/external/wpt/css/CSS2/linebox/vertical-align-baseline-005a.xht [ Failure ] @@ -430,9 +430,6 @@ crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/block-non-replaced-height-005.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-table-zorder-005.xht [ Failure ] -# Inline: atomic inline margins. -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-block-non-replaced-height-002.xht [ Failure ] - # Inline: atomic inline preferred width. crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-block-valign-001.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inline-block-valign-002.xht [ Failure ] @@ -914,8 +911,8 @@ crbug.com/692560 external/wpt/html/semantics/document-metadata/styling/LinkStyle.html [ Failure Pass ] crbug.com/627706 external/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html [ Skip ] # MANIFEST.json contains any *-manual.*. https://github.com/w3c/web-platform-tests/issues/4137 -Bug(github) external/wpt/uievents/keyboard/key-manual.css [ Skip ] -Bug(github) external/wpt/uievents/keyboard/key-manual.js [ Skip ] +Bug(github) external/wpt/uievents/keyboard/key.css [ Skip ] +Bug(github) external/wpt/uievents/keyboard/key.js [ Skip ] crbug.com/698135 external/wpt/editing/run/delete.html [ Crash Failure Timeout ] crbug.com/698165 external/wpt/editing/run/forwarddelete.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 093e9f8..97cce6be 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -3967,18 +3967,6 @@ {} ] ], - "uievents/keyboard/key-manual.css": [ - [ - "/uievents/keyboard/key-manual.css", - {} - ] - ], - "uievents/keyboard/key-manual.js": [ - [ - "/uievents/keyboard/key-manual.js", - {} - ] - ], "uievents/mouse/mouseevent_move_button-manual.html": [ [ "/uievents/mouse/mouseevent_move_button-manual.html", @@ -87640,6 +87628,36 @@ {} ] ], + "html/browsers/offline/appcache/workers/resources/appcache-dedicated-worker-not-in-cache.js": [ + [ + {} + ] + ], + "html/browsers/offline/appcache/workers/resources/appcache-shared-worker-not-in-cache.js": [ + [ + {} + ] + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker-data.py": [ + [ + {} + ] + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker-import.py": [ + [ + {} + ] + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker.manifest": [ + [ + {} + ] + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker.py": [ + [ + {} + ] + ], "html/browsers/offline/application-cache-api/.gitkeep": [ [ {} @@ -105400,6 +105418,16 @@ {} ] ], + "uievents/keyboard/key.css": [ + [ + {} + ] + ], + "uievents/keyboard/key.js": [ + [ + {} + ] + ], "uievents/legacy-domevents-tests/Status.html": [ [ {} @@ -130450,6 +130478,12 @@ {} ] ], + "html/browsers/offline/appcache/workers/appcache-worker.html": [ + [ + "/html/browsers/offline/appcache/workers/appcache-worker.html", + {} + ] + ], "html/browsers/offline/application-cache-api/api_status_idle.html": [ [ "/html/browsers/offline/application-cache-api/api_status_idle.html", @@ -225787,6 +225821,34 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], + "html/browsers/offline/appcache/workers/appcache-worker.html": [ + "d4dc559a600b1d197e7b31f960b396da3faa4e42", + "testharness" + ], + "html/browsers/offline/appcache/workers/resources/appcache-dedicated-worker-not-in-cache.js": [ + "4f2e89ef4b23ff17d6c333831cdd81ebf46a9315", + "support" + ], + "html/browsers/offline/appcache/workers/resources/appcache-shared-worker-not-in-cache.js": [ + "e0ca1027ad1077119b95f6a56055417452ab4b04", + "support" + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker-data.py": [ + "5686f9536fc98675e737d703d054370b1398399a", + "support" + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker-import.py": [ + "8dced5671671d536c1e0bb554bf919f7f2f3861e", + "support" + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker.manifest": [ + "284dcbf9adad4bc5d823e654ca889c08f679735c", + "support" + ], + "html/browsers/offline/appcache/workers/resources/appcache-worker.py": [ + "8681ab72485c543d1e22de75cee685478090a848", + "support" + ], "html/browsers/offline/application-cache-api/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -228644,7 +228706,7 @@ "support" ], "html/editing/activation/OWNERS": [ - "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", + "2764978ea7b3de2789f3e5c8ad8e819a697cedd9", "support" ], "html/editing/activation/click-manual.html": [ @@ -232016,7 +232078,7 @@ "support" ], "html/editing/editing-0/contenteditable/OWNERS": [ - "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", + "2764978ea7b3de2789f3e5c8ad8e819a697cedd9", "support" ], "html/editing/editing-0/contenteditable/contentEditable-invalidvalue.html": [ @@ -232036,7 +232098,7 @@ "support" ], "html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/OWNERS": [ - "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", + "2764978ea7b3de2789f3e5c8ad8e819a697cedd9", "support" ], "html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json": [ @@ -232052,7 +232114,7 @@ "support" ], "html/editing/editing-0/spelling-and-grammar-checking/OWNERS": [ - "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", + "2764978ea7b3de2789f3e5c8ad8e819a697cedd9", "support" ], "html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html": [ @@ -232112,7 +232174,7 @@ "support" ], "html/editing/focus/document-level-focus-apis/OWNERS": [ - "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", + "2764978ea7b3de2789f3e5c8ad8e819a697cedd9", "support" ], "html/editing/focus/document-level-focus-apis/document-level-apis.html": [ @@ -232132,7 +232194,7 @@ "support" ], "html/editing/focus/focus-management/OWNERS": [ - "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", + "2764978ea7b3de2789f3e5c8ad8e819a697cedd9", "support" ], "html/editing/focus/focus-management/focus-event-targets-simple.html": [ @@ -232152,7 +232214,7 @@ "support" ], "html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/OWNERS": [ - "e3e7f3973cf8f9b466d4f22d1ec3b9b9241fb906", + "2764978ea7b3de2789f3e5c8ad8e819a697cedd9", "support" ], "html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html": [ @@ -262048,20 +262110,20 @@ "support" ], "uievents/keyboard/key-101en-us-manual.html": [ - "8c4bedcea88fd39cfe291e40b11c3b0cb510267a", + "0b54b880246409466d57dcbe941b89d74587e8e4", "manual" ], "uievents/keyboard/key-102fr-fr-manual.html": [ - "74ec4ae6f0cfa8ddc2f296d058a70d64977eb28a", + "65b31e543203b36d6a1026ba9da3e60de507cf67", "manual" ], - "uievents/keyboard/key-manual.css": [ + "uievents/keyboard/key.css": [ "54d5f8a452d8bbbd040e66af7594debacb6d0377", - "manual" + "support" ], - "uievents/keyboard/key-manual.js": [ + "uievents/keyboard/key.js": [ "d189977c13fcff73f9604a56a919676930176db4", - "manual" + "support" ], "uievents/legacy-domevents-tests/Status.html": [ "b4cfc46993f2349beca9aa583b1eaf24a1bdfe63",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-101en-us-manual.html b/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-101en-us-manual.html index 8b9cb46..3228c65 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-101en-us-manual.html +++ b/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-101en-us-manual.html
@@ -5,8 +5,8 @@ <title>Keyboard Event Manual Test</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> -<script type="text/javascript" src="key-manual.js" ></script> -<link rel="stylesheet" type="text/css" href="key-manual.css" /> +<script type="text/javascript" src="key.js" ></script> +<link rel="stylesheet" type="text/css" href="key.css" /> </head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-102fr-fr-manual.html b/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-102fr-fr-manual.html index 6521681..c5b51c47 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-102fr-fr-manual.html +++ b/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-102fr-fr-manual.html
@@ -5,8 +5,8 @@ <title>Keyboard Event Manual Test</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> -<script type="text/javascript" src="key-manual.js" ></script> -<link rel="stylesheet" type="text/css" href="key-manual.css" /> +<script type="text/javascript" src="key.js" ></script> +<link rel="stylesheet" type="text/css" href="key.css" /> </head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-manual.css b/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key.css similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-manual.css rename to third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key.css
diff --git a/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-manual.js b/third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key.js similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key-manual.js rename to third_party/WebKit/LayoutTests/external/wpt/uievents/keyboard/key.js
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame-expected.txt index 856e153..87741ca 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame-expected.txt
@@ -1,3 +1,4 @@ + Paused on 'debugger;' resume restartFrame
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame.html deleted file mode 100644 index 7d1ba5d..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame.html +++ /dev/null
@@ -1,76 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function testFunction() -{ - debugger; -} - -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}); - - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedOne; - - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "setTimeout(testFunction, 0)" }); - - var obsoleteTopFrameId; - - function handleDebuggerPausedOne(messageObject) - { - InspectorTest.log("Paused on 'debugger;'"); - - var topFrame = messageObject.params.callFrames[0]; - obsoleteTopFrameId = topFrame.callFrameId; - - InspectorTest.eventHandler["Debugger.paused"] = undefined; - - InspectorTest.sendCommand("Debugger.resume", { }, callbackResume); - } - - function callbackResume(response) - { - InspectorTest.log("resume"); - InspectorTest.log("restartFrame"); - InspectorTest.sendCommand("Debugger.restartFrame", { callFrameId: obsoleteTopFrameId }, callbackRestartFrame); - } - - function callbackRestartFrame(response) - { - logErrorResponse(response); - InspectorTest.log("evaluateOnFrame"); - InspectorTest.sendCommand("Debugger.evaluateOnCallFrame", { callFrameId: obsoleteTopFrameId, expression: "0"} , callbackEvaluate); - } - - function callbackEvaluate(response) - { - logErrorResponse(response); - InspectorTest.log("setVariableValue"); - InspectorTest.sendCommand("Debugger.setVariableValue", { callFrameId: obsoleteTopFrameId, scopeNumber: 0, variableName: "a", newValue: { value: 0 } }, callbackSetVariableValue); - } - - function callbackSetVariableValue(response) - { - logErrorResponse(response); - InspectorTest.completeTest(); - } - - function logErrorResponse(response) - { - if (response.error) { - if (response.error.message.indexOf("Can only perform operation while paused.") != -1) { - InspectorTest.log("PASS, error message as expected"); - return; - } - } - InspectorTest.log("FAIL, unexpected error message"); - InspectorTest.log(JSON.stringify(response)); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame.js new file mode 100644 index 0000000..b9ec2d0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/access-obsolete-frame.js
@@ -0,0 +1,35 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + function logErrorResponse(response) { + if (response.error) { + if (response.error.message.indexOf('Can only perform operation while paused.') != -1) { + testRunner.log('PASS, error message as expected'); + return; + } + } + testRunner.log('FAIL, unexpected error message'); + testRunner.log(JSON.stringify(response)); + } + + dp.Debugger.enable(); + dp.Runtime.evaluate({expression: 'setTimeout(() => { debugger; }, 0)' }); + + var messageObject = await dp.Debugger.oncePaused(); + testRunner.log(`Paused on 'debugger;'`); + var topFrame = messageObject.params.callFrames[0]; + var obsoleteTopFrameId = topFrame.callFrameId; + + await dp.Debugger.resume(); + testRunner.log('resume'); + testRunner.log('restartFrame'); + + logErrorResponse(await dp.Debugger.restartFrame({callFrameId: obsoleteTopFrameId})); + testRunner.log('evaluateOnFrame'); + + logErrorResponse(await dp.Debugger.evaluateOnCallFrame({callFrameId: obsoleteTopFrameId, expression: '0'})); + testRunner.log('setVariableValue'); + + logErrorResponse(await dp.Debugger.setVariableValue({callFrameId: obsoleteTopFrameId, scopeNumber: 0, variableName: 'a', newValue: { value: 0 }})); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation-expected.txt index d309d42..ccc8515 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation-expected.txt
@@ -1,3 +1,4 @@ + Paused on 'debugger;' Top frame location: {"scriptId":"42","lineNumber":8,"columnNumber":4} Top frame functionLocation: {"scriptId":"42","lineNumber":5,"columnNumber":21}
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation.html deleted file mode 100644 index 84fab01dd..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation.html +++ /dev/null
@@ -1,33 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function testFunction() -{ - var a = 2; - debugger; -} - -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}); - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPaused; - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "setTimeout(testFunction, 0)" }); - - function handleDebuggerPaused(messageObject) - { - InspectorTest.log("Paused on 'debugger;'"); - var topFrame = messageObject.params.callFrames[0]; - topFrame.location.scriptId = "42"; - topFrame.functionLocation.scriptId = "42"; - InspectorTest.log("Top frame location: " + JSON.stringify(topFrame.location)); - InspectorTest.log("Top frame functionLocation: " + JSON.stringify(topFrame.functionLocation)); - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation.js new file mode 100644 index 0000000..f7f3db31 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/call-frame-functionLocation.js
@@ -0,0 +1,26 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + dp.Debugger.enable(); + dp.Runtime.evaluate({expression: ` + + + + +function testFunction() +{ + var a = 2; + debugger; +} +setTimeout(testFunction, 0); + `}); + + var messageObject = await dp.Debugger.oncePaused(); + testRunner.log(`Paused on 'debugger;'`); + var topFrame = messageObject.params.callFrames[0]; + topFrame.location.scriptId = '42'; + topFrame.functionLocation.scriptId = '42'; + testRunner.log('Top frame location: ' + JSON.stringify(topFrame.location)); + testRunner.log('Top frame functionLocation: ' + JSON.stringify(topFrame.functionLocation)); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation-expected.txt index d0c6ce7..404cd9ac 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation-expected.txt
@@ -1,3 +1,4 @@ + Paused on debugger statement Paused after continueToLocation Stopped on line 8, expected 8, requested 8, (0-based numbers).
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html deleted file mode 100644 index 5ae2992..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html +++ /dev/null
@@ -1,103 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script type="text/javascript" src="resources/statements.js"></script> -<script> - -function test() -{ - var scenario = [ - // requested line number, expected control parameter 'step', expected line number - [ 8, 1, 8 ], - [ 8, 1, 8 ], - [ 12, 6, 17 ], - [ 13, 6, 17 ], - [ 17, 6, 17 ], - [ 17, 6, 17 ], - ]; - - InspectorTest.sendCommand("Debugger.enable", {}); - - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "statementsExample" }, callbackEvalFunctionObject); - - function callbackEvalFunctionObject(response) - { - var functionObjectId = response.result.result.objectId; - InspectorTest.sendCommand("Runtime.getProperties", { objectId: functionObjectId }, callbackFunctionDetails); - } - - function callbackFunctionDetails(response) - { - var result = response.result; - var scriptId; - for (var prop of result.internalProperties) { - if (prop.name === "[[FunctionLocation]]") - scriptId = prop.value.value.scriptId; - } - - nextScenarioStep(0); - - function nextScenarioStep(pos) - { - if (pos < scenario.length) - gotoSinglePassChain(scriptId, scenario[pos][0], scenario[pos][1], scenario[pos][2], nextScenarioStep.bind(this, pos + 1)); - else - InspectorTest.completeTest(); - } - } - - function gotoSinglePassChain(scriptId, lineNumber, expectedResult, expectedLineNumber, next) - { - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedOne; - - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "setTimeout(statementsExample, 0)" }); - - function handleDebuggerPausedOne(messageObject) - { - InspectorTest.log("Paused on debugger statement"); - - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedTwo; - - InspectorTest.sendCommand("Debugger.continueToLocation", { location: { scriptId: scriptId, lineNumber: lineNumber, columnNumber: 0} }, logContinueToLocation); - - function logContinueToLocation(response) - { - if (response.error) { - InspectorTest.log("Failed to execute continueToLocation " + JSON.stringify(response.error)); - InspectorTest.completeTest(); - } - } - } - function handleDebuggerPausedTwo(messageObject) - { - InspectorTest.log("Paused after continueToLocation"); - var actualLineNumber = messageObject.params.callFrames[0].location.lineNumber; - - InspectorTest.log("Stopped on line " + actualLineNumber + ", expected " + expectedLineNumber + ", requested " + lineNumber + ", (0-based numbers)."); - - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedUnexpected; - - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "statementsExample.step" }, callbackStepEvaluate); - } - - function callbackStepEvaluate(response) - { - var resultValue = response.result.result.value; - InspectorTest.log("Control parameter 'step' calculation result: " + resultValue + ", expected: " + expectedResult); - InspectorTest.log(resultValue == expectedResult ? "SUCCESS" : "FAIL"); - InspectorTest.sendCommand("Debugger.resume", { }); - next(); - } - - function handleDebuggerPausedUnexpected(messageObject) - { - InspectorTest.log("Unexpected debugger pause"); - InspectorTest.completeTest(); - } - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.js new file mode 100644 index 0000000..466535a --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.js
@@ -0,0 +1,79 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + function statementsExample() + { + var self = arguments.callee; + + debugger; + + self.step = 1; + + self.step = 2; + + void [ + self.step = 3, + self.step = 4, + self.step = 5, + self.step = 6 + ]; + + self.step = 7; + } + + var scenarios = [ + // requested line number, expected control parameter 'step', expected line number + [ 8, 1, 8 ], + [ 8, 1, 8 ], + [ 12, 6, 17 ], + [ 13, 6, 17 ], + [ 17, 6, 17 ], + [ 17, 6, 17 ], + ]; + + dp.Debugger.enable(); + var functionResponse = await dp.Runtime.evaluate({expression: statementsExample.toString() + '; statementsExample'}); + var functionObjectId = functionResponse.result.result.objectId; + + var detailsResponse = await dp.Runtime.getProperties({objectId: functionObjectId}); + var scriptId; + for (var prop of detailsResponse.result.internalProperties) { + if (prop.name === '[[FunctionLocation]]') + scriptId = prop.value.value.scriptId; + } + + for (var scenario of scenarios) { + var lineNumber = scenario[0]; + var expectedResult = scenario[1]; + var expectedLineNumber = scenario[2]; + dp.Runtime.evaluate({expression: 'setTimeout(statementsExample, 0)' }); + await dp.Debugger.oncePaused(); + testRunner.log('Paused on debugger statement'); + + var continueToLocationResponse = await dp.Debugger.continueToLocation({location: {scriptId, lineNumber, columnNumber: 0}}); + if (continueToLocationResponse.error) { + testRunner.log('Failed to execute continueToLocation ' + JSON.stringify(continueToLocationResponse.error)); + testRunner.completeTest(); + return; + } + + var messageObject = await dp.Debugger.oncePaused(); + testRunner.log('Paused after continueToLocation'); + var actualLineNumber = messageObject.params.callFrames[0].location.lineNumber; + testRunner.log('Stopped on line ' + actualLineNumber + ', expected ' + expectedLineNumber + ', requested ' + lineNumber + ', (0-based numbers).'); + + dp.Debugger.onPaused(handleDebuggerPausedUnexpected); + var resultValue = (await dp.Runtime.evaluate({expression: 'statementsExample.step' })).result.result.value; + testRunner.log(`Control parameter 'step' calculation result: ${resultValue}, expected: ${expectedResult}`); + testRunner.log(resultValue == expectedResult ? 'SUCCESS' : 'FAIL'); + dp.Debugger.resume(); + dp.Debugger.offPaused(handleDebuggerPausedUnexpected); + + function handleDebuggerPausedUnexpected() { + testRunner.log('Unexpected debugger pause'); + testRunner.completeTest(); + } + } + + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.html deleted file mode 100644 index 5bacfae..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.html +++ /dev/null
@@ -1,39 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function foo() -{ - return 239; -} - -function test() -{ - InspectorTest.sendCommandOrDie("Debugger.enable", {}); - InspectorTest.eventHandler["Debugger.paused"] = debuggerPaused; - InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "(function boo() { setTimeout(foo, 0); debugger; })()" }); - - var actions = [ "stepInto", "stepInto", "stepInto" ]; - function debuggerPaused(result) - { - InspectorTest.log("Stack trace:"); - for (var callFrame of result.params.callFrames) - InspectorTest.log(callFrame.functionName + ':' + callFrame.location.lineNumber + ":" + callFrame.location.columnNumber); - InspectorTest.log(""); - - var action = actions.shift(); - if (!action) { - InspectorTest.sendCommandOrDie("Debugger.resume", {}, () => InspectorTest.completeTest()); - return; - } - InspectorTest.log("Perform " + action); - InspectorTest.sendCommandOrDie("Debugger." + action, {}); - } -} -</script> -</head> -<body onLoad="runTest();"> -Check that stepInto at then end of the script go to next user script instead InjectedScriptSource.js. -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.js new file mode 100644 index 0000000..64fd2d3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.js
@@ -0,0 +1,38 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank('Check that stepInto at then end of the script go to next user script instead InjectedScriptSource.js.'); + + function logStack(event) { + testRunner.log('Stack trace:'); + for (var callFrame of event.params.callFrames) + testRunner.log(callFrame.functionName + ':' + callFrame.location.lineNumber + ':' + callFrame.location.columnNumber); + testRunner.log(''); + } + + dp.Debugger.enable(); + await session.evaluate(` + + + + + + function foo() { + return 239; + }`); + dp.Runtime.evaluate({expression: '(function boo() { setTimeout(foo, 0); debugger; })()' }); + + logStack(await dp.Debugger.oncePaused()); + testRunner.log('Perform stepInto'); + dp.Debugger.stepInto(); + + logStack(await dp.Debugger.oncePaused()); + testRunner.log('Perform stepInto'); + dp.Debugger.stepInto(); + + logStack(await dp.Debugger.oncePaused()); + testRunner.log('Perform stepInto'); + dp.Debugger.stepInto(); + + logStack(await dp.Debugger.oncePaused()); + await dp.Debugger.resume(); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page-expected.txt index 81e00ce..aa6355b6 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page-expected.txt
@@ -1,3 +1,4 @@ + Started worker Paused on 'debugger;' Worker created
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.html deleted file mode 100644 index ddae332..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.html +++ /dev/null
@@ -1,80 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -var worker; - -function testFunction() -{ - debugger; -} - -function startWorkerAndRunTest() -{ - worker = new Worker("resources/dedicated-worker.js"); - worker.onmessage = function(event) { }; - worker.postMessage(1); - log("Started worker"); - runTest(); -} - -function test() -{ - var workerId; - var workerRequestId = 1; - - function sendCommandToWorker(method, params) - { - InspectorTest.sendCommand("Target.sendMessageToTarget", - { - "targetId": workerId, - "message": JSON.stringify({ "method": method, - "params": params, - "id": workerRequestId }) - }); - return workerRequestId++; - } - - InspectorTest.sendCommand("Debugger.enable", {}); - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedInTestFunction; - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "testFunction()" }); - - function handleDebuggerPausedInTestFunction(messageObject) - { - InspectorTest.log("Paused on 'debugger;'"); - InspectorTest.sendCommand("Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: false}, didEnableWorkerDebugging); - } - - function didEnableWorkerDebugging(messageObject) - { - if ("error" in messageObject) { - InspectorTest.log("FAIL: Couldn't enable worker debugger: " + messageObject.error.message); - InspectorTest.completeTest(); - } - } - - var savedWorkerRequestId = -1; - InspectorTest.eventHandler["Target.attachedToTarget"] = function(messageObject) - { - workerId = messageObject["params"]["targetInfo"]["targetId"]; - InspectorTest.log("Worker created"); - InspectorTest.log("didConnectToWorker"); - savedWorkerRequestId = sendCommandToWorker("Runtime.evaluate", { "expression": "1+1"}); - } - - InspectorTest.eventHandler["Target.receivedMessageFromTarget"] = function(messageObject) - { - var message = JSON.parse(messageObject["params"]["message"]); - if (message["id"] === savedWorkerRequestId) { - var value = message["result"]["result"]["value"]; - InspectorTest.log("Successfully evaluated, result: " + value); - InspectorTest.completeTest(); - } - } -} -</script> -</head> -<body onLoad="startWorkerAndRunTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js new file mode 100644 index 0000000..76ede5e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js
@@ -0,0 +1,39 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + await session.evaluate(` + window.worker = new Worker('${testRunner.url('resources/dedicated-worker.js')}'); + window.worker.onmessage = function(event) { }; + window.worker.postMessage(1); + `); + testRunner.log('Started worker'); + + var workerRequestId = 1; + function sendCommandToWorker(method, params) { + var message = {method, params, id: workerRequestId}; + dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); + return workerRequestId++; + } + + dp.Debugger.enable(); + dp.Runtime.evaluate({expression: 'debugger;' }); + await dp.Debugger.oncePaused(); + testRunner.log(`Paused on 'debugger;'`); + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + + var messageObject = await dp.Target.onceAttachedToTarget(); + var workerId = messageObject.params.targetInfo.targetId; + testRunner.log('Worker created'); + testRunner.log('didConnectToWorker'); + + var savedWorkerRequestId = sendCommandToWorker('Runtime.evaluate', {expression: '1+1'}); + dp.Target.onReceivedMessageFromTarget(messageObject => { + var message = JSON.parse(messageObject.params.message); + if (message.id === savedWorkerRequestId) { + var value = message.result.result.value; + testRunner.log('Successfully evaluated, result: ' + value); + testRunner.completeTest(); + } + }); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-expected.txt index e412394..bd6d733 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-expected.txt
@@ -1,3 +1,4 @@ + Started worker Worker created didConnectToWorker
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt index ab9d5310a..0b8048b 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt
@@ -1,3 +1,4 @@ + Started worker Worker created didConnectToWorker
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.html deleted file mode 100644 index 5d3c19d..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.html +++ /dev/null
@@ -1,86 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -var worker; -function startWorkerAndRunTest() -{ - worker = new Worker("resources/dedicated-worker-loop.js"); - worker.onmessage = function(event) - { - if (event.data === "WorkerMessageReceived") - evaluateInFrontend("InspectorTest.workerMessageReceived()"); - }; - log("Started worker"); - runTest(); -} - -function test() -{ - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) - { - InspectorTest.sendCommand("Target.sendMessageToTarget", - { - "targetId": workerId, - "message": JSON.stringify({ "method": method, - "params": params, - "id": workerRequestId }) - }); - return workerRequestId++; - } - - function didEnableWorkerDebugging(messageObject) - { - if ("error" in messageObject) { - InspectorTest.log("FAIL: Couldn't enable worker debugger: " + messageObject.error.message); - InspectorTest.completeTest(); - } - } - InspectorTest.sendCommand("Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: false}, didEnableWorkerDebugging); - - var evaluateRequestId = -1; - var debuggerEnableRequestId = -1; - InspectorTest.eventHandler["Target.attachedToTarget"] = function(messageObject) - { - workerId = messageObject["params"]["targetInfo"]["targetId"]; - InspectorTest.log("Worker created"); - InspectorTest.log("didConnectToWorker"); - // Enable debugger so that V8 can interrupt and handle inspector commands while there is a script running in a tight loop. - debuggerEnableRequestId = sendCommandToWorker("Debugger.enable", {}); - } - - InspectorTest.workerMessageReceived = function() - { - evaluateRequestId = sendCommandToWorker("Runtime.evaluate", { "expression": "message_id > 1"}); - } - - InspectorTest.eventHandler["Target.receivedMessageFromTarget"] = function(messageObject) - { - var message = JSON.parse(messageObject["params"]["message"]); - if (message["id"] === debuggerEnableRequestId) { - InspectorTest.log("Did enable debugger"); - // Start tight loop in the worker. - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "worker.postMessage(1)" }, didPostMessageToWorker); - function didPostMessageToWorker() - { - InspectorTest.log("Did post message to worker"); - } - } - if (message["id"] === evaluateRequestId) { - var value = message["result"]["result"]["value"]; - if (value === true) - InspectorTest.log("SUCCESS: evaluated, result: " + value); - else - InspectorTest.log("FAIL: evaluated, result: " + value); - InspectorTest.completeTest(); - } - } -} -</script> -</head> -<body onLoad="startWorkerAndRunTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.js new file mode 100644 index 0000000..ec3325f --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.js
@@ -0,0 +1,54 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + await session.evaluate(` + window.worker = new Worker('${testRunner.url('resources/dedicated-worker-loop.js')}'); + var resolve; + window.workerMessageReceivedPromise = new Promise(f => resolve = f); + window.worker.onmessage = function(event) { + if (event.data === 'WorkerMessageReceived') + resolve(); + }; + `); + testRunner.log('Started worker'); + + var workerId; + var workerRequestId = 1; + function sendCommandToWorker(method, params) { + var message = {method, params, id: workerRequestId}; + dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); + return workerRequestId++; + } + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + + var debuggerEnableRequestId = -1; + var evaluateRequestId = -1; + + dp.Target.onReceivedMessageFromTarget(async messageObject => { + var message = JSON.parse(messageObject.params.message); + if (message.id === debuggerEnableRequestId) { + testRunner.log('Did enable debugger'); + // Start tight loop in the worker. + await dp.Runtime.evaluate({expression: 'worker.postMessage(1)' }); + testRunner.log('Did post message to worker'); + } + if (message.id === evaluateRequestId) { + var value = message.result.result.value; + if (value === true) + testRunner.log('SUCCESS: evaluated, result: ' + value); + else + testRunner.log('FAIL: evaluated, result: ' + value); + testRunner.completeTest(); + } + }); + + workerId = (await dp.Target.onceAttachedToTarget()).params.targetInfo.targetId; + testRunner.log('Worker created'); + testRunner.log('didConnectToWorker'); + // Enable debugger so that V8 can interrupt and handle inspector commands while there is a script running in a tight loop. + debuggerEnableRequestId = sendCommandToWorker('Debugger.enable', {}); + + await session.evaluateAsync('workerMessageReceivedPromise'); + evaluateRequestId = sendCommandToWorker('Runtime.evaluate', { 'expression': 'message_id > 1'}); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker.html deleted file mode 100644 index 1d33b8d..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker.html +++ /dev/null
@@ -1,69 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - - -var worker; - -function startWorkerAndRunTest() -{ - worker = new Worker("resources/dedicated-worker.js"); - worker.onmessage = function(event) { }; - worker.postMessage(1); - log("Started worker"); - runTest(); -} - - -function test() -{ - - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) - { - InspectorTest.sendCommand("Target.sendMessageToTarget", - { - "targetId": workerId, - "message": JSON.stringify({ "method": method, - "params": params, - "id": workerRequestId++ }) - }); - } - - function didEnableWorkerDebugging(messageObject) - { - if ("error" in messageObject) { - InspectorTest.log("FAIL: Couldn't enable worker debugger: " + messageObject.error.message); - InspectorTest.completeTest(); - } - } - InspectorTest.sendCommand("Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: false}, didEnableWorkerDebugging); - - - InspectorTest.eventHandler["Target.attachedToTarget"] = function(messageObject) - { - workerId = messageObject["params"]["targetInfo"]["targetId"]; - InspectorTest.log("Worker created"); - InspectorTest.log("didConnectToWorker"); - sendCommandToWorker("Debugger.enable", {}); - sendCommandToWorker("Debugger.pause", {}); - } - - InspectorTest.eventHandler["Target.receivedMessageFromTarget"] = function(messageObject) - { - var message = JSON.parse(messageObject["params"]["message"]); - if (message["method"] === "Debugger.paused") { - InspectorTest.log("SUCCESS: Worker paused"); - sendCommandToWorker("Debugger.disable", {}); - InspectorTest.completeTest(); - } - } - -} -</script> -</head> -<body onLoad="startWorkerAndRunTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker.js new file mode 100644 index 0000000..90542a2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-dedicated-worker.js
@@ -0,0 +1,35 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + await session.evaluate(` + window.worker = new Worker('${testRunner.url('resources/dedicated-worker.js')}'); + window.worker.onmessage = function(event) { }; + window.worker.postMessage(1); + `); + testRunner.log('Started worker'); + + var workerRequestId = 1; + function sendCommandToWorker(method, params) { + var message = {method, params, id: workerRequestId}; + dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); + return workerRequestId++; + } + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + + var messageObject = await dp.Target.onceAttachedToTarget(); + var workerId = messageObject.params.targetInfo.targetId; + testRunner.log('Worker created'); + testRunner.log('didConnectToWorker'); + sendCommandToWorker('Debugger.enable', {}); + sendCommandToWorker('Debugger.pause', {}); + + dp.Target.onReceivedMessageFromTarget(messageObject => { + var message = JSON.parse(messageObject.params.message); + if (message.method === 'Debugger.paused') { + testRunner.log('SUCCESS: Worker paused'); + sendCommandToWorker('Debugger.disable', {}); + testRunner.completeTest(); + } + }); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop-expected.txt index 938e588..a769f3e 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop-expected.txt
@@ -1,4 +1,6 @@ + didEval didFireTimer SUCCESS: Paused +SUCCESS: Resumed
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop.html deleted file mode 100644 index fac7b51..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop.html +++ /dev/null
@@ -1,62 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function testFunction() -{ - setTimeout(hotFunction, 0); -} - -var terminated = false; -function hotFunction() { - evaluateInFrontend("InspectorTest.didFireTimer()"); - - var message_id = 1; - var ts = Date.now(); - while (!terminated) { - // Without this try/catch v8 will optimize the function and break will not work. - try { - if (Date.now() - ts > 1000) { - ts = Date.now(); - console.error("Message #" + message_id++); - } - } catch (e) { - } - } -} - -function test() -{ - InspectorTest.sendCommand("Inspector.enable", {}); - InspectorTest.sendCommand("Debugger.enable", {}, didEnableDebugger); - function didEnableDebugger() - { - // Start tight loop in page. - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "testFunction()" }, didEval); - function didEval() - { - InspectorTest.log("didEval"); - } - } - - InspectorTest.didFireTimer = function() - { - InspectorTest.log("didFireTimer"); - InspectorTest.sendCommand("Debugger.pause", { }); - } - - InspectorTest.eventHandler["Debugger.paused"] = function(messageObject) - { - var message = messageObject["params"]["message"]; - InspectorTest.log("SUCCESS: Paused"); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "terminated = true;" }); - InspectorTest.sendCommand("Debugger.resume", { }); - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop.js new file mode 100644 index 0000000..f56dc97e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-pause-in-tight-loop.js
@@ -0,0 +1,41 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + await dp.Runtime.enable(); + await dp.Debugger.enable(); + + // Start tight loop in page. + session.evaluate(` + var terminated = false; + function hotFunction() { + console.log('hi'); + var message_id = 1; + var ts = Date.now(); + while (!terminated) { + // Without this try/catch v8 will optimize the function and break will not work. + try { + if (Date.now() - ts > 1000) { + ts = Date.now(); + console.error('Message #' + message_id++); + } + } catch (e) { + } + } + } + setTimeout(hotFunction, 0); + `); + testRunner.log('didEval'); + + await dp.Runtime.onceConsoleAPICalled(); + testRunner.log('didFireTimer'); + + dp.Debugger.pause(); + await dp.Debugger.oncePaused(); + testRunner.log('SUCCESS: Paused'); + + dp.Runtime.evaluate({expression: 'terminated = true;' }); + dp.Debugger.resume(); + await dp.Debugger.onceResumed(); + testRunner.log('SUCCESS: Resumed'); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt index 4b7e1a3..f1a2108 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt
@@ -1,3 +1,4 @@ + { result : [ [0] : {
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.html deleted file mode 100644 index a0357b3..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.html +++ /dev/null
@@ -1,50 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function testFunction() -{ - for (var a of [1]) { - ++a; - debugger; - } -} - -function test() -{ - InspectorTest.sendCommandOrDie("Debugger.enable", {}); - InspectorTest.eventHandler["Debugger.paused"] = dumpScopeOnPause; - InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "testFunction()" }); - - var waitScopeObjects = 0; - function dumpScopeOnPause(message) - { - var scopeChain = message.params.callFrames[0].scopeChain; - var localScopeObjectIds = []; - for (var scope of scopeChain) { - if (scope.type === "local") - localScopeObjectIds.push(scope.object.objectId); - } - waitScopeObjects = localScopeObjectIds.length; - if (!waitScopeObjects) { - InspectorTest.completeTest(); - } else { - for (var objectId of localScopeObjectIds) - InspectorTest.sendCommandOrDie("Runtime.getProperties", { "objectId" : objectId }, dumpProperties); - } - } - - function dumpProperties(message) - { - InspectorTest.logObject(message); - --waitScopeObjects; - if (!waitScopeObjects) - InspectorTest.sendCommandOrDie("Debugger.resume", {}, () => InspectorTest.completeTest()); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.js new file mode 100644 index 0000000..a9e8871 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.js
@@ -0,0 +1,28 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + dp.Debugger.enable(); + dp.Runtime.evaluate({expression: ` + function testFunction() { + for (var a of [1]) { + ++a; + debugger; + } + } + testFunction(); + `}); + + var message = await dp.Debugger.oncePaused(); + var scopeChain = message.params.callFrames[0].scopeChain; + var localScopeObjectIds = []; + for (var scope of scopeChain) { + if (scope.type === 'local') + localScopeObjectIds.push(scope.object.objectId); + } + + for (var objectId of localScopeObjectIds) + testRunner.logObject((await dp.Runtime.getProperties({objectId})).result); + + await dp.Debugger.resume(); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt index 9b5bec7..287712b 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns-expected.txt
@@ -1,25 +1,26 @@ + Pattern parser error: Uncaught SyntaxError: Invalid regular expression: /(foo([)/: Unterminated character class Paused in (...):1 Paused in (...):1 Paused in -qwe:21 -baz:29 +qwe:4 +baz:4 (...):1 Paused in -bar:7 -foo:13 -qwe:21 -baz:29 +bar:4 +foo:4 +qwe:4 +baz:4 (...):1 Paused in -qwe:22 -baz:29 +qwe:5 +baz:4 (...):1 Paused in -qwe:23 -baz:29 +qwe:6 +baz:4 (...):1 Paused in (...):1
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns.html deleted file mode 100644 index 07ec913271..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns.html +++ /dev/null
@@ -1,67 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> -function bar() -{ - return 42; -} -</script> -<script> -function foo() -{ - var a = bar(); - return a + 1; -} -//# sourceURL=foo.js -</script> -<script> -function qwe() -{ - var a = foo(); - return a + 1; -} -//# sourceURL=qwe.js -</script> -<script> -function baz() -{ - var a = qwe(); - return a + 1; -} -//# sourceURL=baz.js -</script> -<script> -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}); - InspectorTest.sendCommand("Debugger.setBlackboxPatterns", { patterns: [ "foo([" ] }, dumpError); - - function dumpError(message) - { - InspectorTest.log(message.error.message); - InspectorTest.eventHandler["Debugger.paused"] = dumpStackAndRunNextCommand; - InspectorTest.sendCommandOrDie("Debugger.setBlackboxPatterns", { patterns: [ "baz\.js", "foo\.js" ] }); - InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "debugger;baz()" }); - } - - var commands = [ "stepInto", "stepInto", "stepInto", "stepOut", "stepInto", "stepInto" ]; - function dumpStackAndRunNextCommand(message) - { - InspectorTest.log("Paused in"); - var callFrames = message.params.callFrames; - for (var callFrame of callFrames) - InspectorTest.log((callFrame.functionName || "(...)") + ":" + (callFrame.location.lineNumber + 1)); - var command = commands.shift(); - if (!command) { - InspectorTest.completeTest(); - return; - } - InspectorTest.sendCommandOrDie("Debugger." + command, {}); - } - -} -</script> -</head> -<body onLoad="runTest();"></body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns.js new file mode 100644 index 0000000..65cc402 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setBlackboxPatterns.js
@@ -0,0 +1,74 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + await session.evaluate(` + function bar() + { + return 42; + } + `); + + await session.evaluate(` + function foo() + { + var a = bar(); + return a + 1; + } + //# sourceURL=foo.js + `); + + await session.evaluate(` + function qwe() + { + var a = foo(); + return a + 1; + } + //# sourceURL=qwe.js + `); + + await session.evaluate(` + function baz() + { + var a = qwe(); + return a + 1; + } + //# sourceURL=baz.js + `); + + function logStack(message) { + testRunner.log('Paused in'); + var callFrames = message.params.callFrames; + for (var callFrame of callFrames) + testRunner.log((callFrame.functionName || '(...)') + ':' + (callFrame.location.lineNumber + 1)); + } + + dp.Debugger.enable(); + var message = await dp.Debugger.setBlackboxPatterns({patterns: ['foo([']}); + testRunner.log(message.error.message); + + dp.Debugger.setBlackboxPatterns({patterns: ['baz\.js', 'foo\.js']}); + dp.Runtime.evaluate({expression: 'debugger;baz()' }); + logStack(await dp.Debugger.oncePaused()); + + dp.Debugger.stepInto(); + logStack(await dp.Debugger.oncePaused()); + + dp.Debugger.stepInto(); + logStack(await dp.Debugger.oncePaused()); + + dp.Debugger.stepInto(); + logStack(await dp.Debugger.oncePaused()); + + dp.Debugger.stepOut(); + logStack(await dp.Debugger.oncePaused()); + + dp.Debugger.stepInto(); + logStack(await dp.Debugger.oncePaused()); + + dp.Debugger.stepInto(); + logStack(await dp.Debugger.oncePaused()); + + await dp.Debugger.resume(); + testRunner.completeTest(); +}) +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint-expected.txt index 3b141a7..77c15196 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint-expected.txt
@@ -1,3 +1,4 @@ + PASS: Debugger was enabled Error on attempt to set event listener breakpoint when DOM is disabled: undefined PASS: DOM was enabled
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint.html deleted file mode 100644 index cafebf4f..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint.html +++ /dev/null
@@ -1,69 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}, setEventListenerBreakpointWhenDOMDisabled); - - function finishIfError(message) - { - if (message.result) - return; - InspectorTest.log("FAIL: " + JSON.stringify(message)); - InspectorTest.completeTest(); - } - - function setEventListenerBreakpointWhenDOMDisabled(message) - { - finishIfError(message); - InspectorTest.log("PASS: Debugger was enabled"); - InspectorTest.sendCommand("DOMDebugger.setEventListenerBreakpoint", {'eventName':'click'}, enableDOMAgent); - } - - function enableDOMAgent(message) - { - InspectorTest.log("Error on attempt to set event listener breakpoint when DOM is disabled: " + JSON.stringify(message.error)); - InspectorTest.sendCommand("DOM.enable", {}, setEventListenerBreakpoint); - } - - function setEventListenerBreakpoint(message) - { - finishIfError(message); - InspectorTest.log("PASS: DOM was enabled"); - InspectorTest.sendCommand("DOMDebugger.setEventListenerBreakpoint", {'eventName':'click'}, disableDOMAgent); - } - - - function disableDOMAgent(message) - { - finishIfError(message); - InspectorTest.log("PASS: Listener was set."); - InspectorTest.sendCommand("DOM.disable", {}, disableDOMAgent2); - } - - function disableDOMAgent2(message) - { - finishIfError(message); - InspectorTest.log("PASS: DOM agent was disabled successfully."); - InspectorTest.sendCommand("DOM.disable", {}, finish); - } - - function finish(message) - { - if (!message.error) { - InspectorTest.log("FAIL: we expected an error but it wasn't happen."); - InspectorTest.completeTest(); - return; - } - - InspectorTest.log("PASS: The second attempt to disable DOM agent failed as expected."); - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint.js new file mode 100644 index 0000000..15ff82f --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setEventListenerBreakpoint.js
@@ -0,0 +1,32 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + function finishIfError(message) { + if (message.result) + return; + testRunner.log('FAIL: ' + JSON.stringify(message)); + testRunner.completeTest(); + } + + finishIfError(await dp.Debugger.enable()); + testRunner.log('PASS: Debugger was enabled'); + + var errorResponse = dp.DOMDebugger.setEventListenerBreakpoint({eventName: 'click'}); + testRunner.log('Error on attempt to set event listener breakpoint when DOM is disabled: ' + JSON.stringify(errorResponse.error)); + + finishIfError(await dp.DOM.enable()); + testRunner.log('PASS: DOM was enabled'); + + finishIfError(await dp.DOMDebugger.setEventListenerBreakpoint({eventName:'click'})); + testRunner.log('PASS: Listener was set.'); + + finishIfError(await dp.DOM.disable()); + testRunner.log('PASS: DOM agent was disabled successfully.'); + + var message = await dp.DOM.disable(); + if (!message.error) + testRunner.log(`FAIL: we expected an error but it wasn't happen.`); + else + testRunner.log('PASS: The second attempt to disable DOM agent failed as expected.'); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop-expected.txt index 1eb72fb6..c4ac494d 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop-expected.txt
@@ -1,3 +1,4 @@ + Started worker Worker created didConnectToWorker
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.html deleted file mode 100644 index fd20f46..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.html +++ /dev/null
@@ -1,78 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -var worker; -function startWorkerAndRunTest() -{ - worker = new Worker("resources/dedicated-worker-string-setTimeout.js"); - log("Started worker"); - runTest(); -} - -function test() -{ - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) - { - InspectorTest.sendCommand("Target.sendMessageToTarget", - { - "targetId": workerId, - "message": JSON.stringify({ "method": method, - "params": params, - "id": workerRequestId }) - }); - return workerRequestId++; - } - - function didEnableWorkerDebugging(messageObject) - { - if ("error" in messageObject) { - InspectorTest.log("FAIL: Couldn't enable worker debugger: " + messageObject.error.message); - InspectorTest.completeTest(); - } - } - InspectorTest.sendCommand("Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: false}, didEnableWorkerDebugging); - - var debuggerEnableRequestId = -1; - InspectorTest.eventHandler["Target.attachedToTarget"] = function(messageObject) - { - workerId = messageObject["params"]["targetInfo"]["targetId"]; - InspectorTest.log("Worker created"); - InspectorTest.log("didConnectToWorker"); - debuggerEnableRequestId = sendCommandToWorker("Debugger.enable", {}); - } - - var postMessageToWorker = false; - - InspectorTest.eventHandler["Target.receivedMessageFromTarget"] = function(messageObject) - { - var message = JSON.parse(messageObject["params"]["message"]); - if (message["id"] === debuggerEnableRequestId) { - InspectorTest.log("Did enable debugger"); - // Start setTimeout. - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "worker.postMessage(1)" }, didPostMessageToWorker); - function didPostMessageToWorker() - { - postMessageToWorker = true; - InspectorTest.log("Did post message to worker"); - } - } - - if (postMessageToWorker && message["method"] === "Debugger.scriptParsed") { - var sourceUrl = message["params"]["url"]; - if (!sourceUrl) - InspectorTest.log("SUCCESS: script created from string parameter of setTimeout has no url"); - else - InspectorTest.log("FAIL: script created from string parameter of setTimeout has url " + sourceUrl); - InspectorTest.completeTest(); - } - } -} -</script> -</head> -<body onLoad="startWorkerAndRunTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.js new file mode 100644 index 0000000..7133bb2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.js
@@ -0,0 +1,47 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + await session.evaluate(` + window.worker = new Worker('${testRunner.url('resources/dedicated-worker-string-setTimeout.js')}'); + window.worker.onmessage = function(event) { }; + window.worker.postMessage(1); + `); + testRunner.log('Started worker'); + + var workerId; + var workerRequestId = 1; + function sendCommandToWorker(method, params) { + var message = {method, params, id: workerRequestId}; + dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); + return workerRequestId++; + } + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + + var messageObject = await dp.Target.onceAttachedToTarget(); + workerId = messageObject.params.targetInfo.targetId; + testRunner.log('Worker created'); + testRunner.log('didConnectToWorker'); + + var debuggerEnableRequestId = sendCommandToWorker('Debugger.enable', {}); + var postMessageToWorker = false; + dp.Target.onReceivedMessageFromTarget(async messageObject => { + var message = JSON.parse(messageObject.params.message); + if (message.id === debuggerEnableRequestId) { + testRunner.log('Did enable debugger'); + // Start setTimeout. + await dp.Runtime.evaluate({expression: 'worker.postMessage(1)'}); + postMessageToWorker = true; + testRunner.log('Did post message to worker'); + } + + if (postMessageToWorker && message.method === 'Debugger.scriptParsed') { + var sourceUrl = message.params.url; + if (!sourceUrl) + testRunner.log('SUCCESS: script created from string parameter of setTimeout has no url'); + else + testRunner.log('FAIL: script created from string parameter of setTimeout has url ' + sourceUrl); + testRunner.completeTest(); + } + }); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt index ecdb5d20..776e622 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt
@@ -1,5 +1,4 @@ Tests that dedicated worker won't crash on attempt to step into.Bug 232392. - Started worker Worker created SUCCESS: Worker paused
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.html deleted file mode 100644 index 6822980..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.html +++ /dev/null
@@ -1,73 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> -var worker; - -function startWorker() -{ - worker = new Worker("resources/dedicated-worker-step-into.js"); - worker.onmessage = function(event) { }; - worker.postMessage(1); - log("Started worker"); -} - - -function test() -{ - - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) - { - InspectorTest.sendCommand("Target.sendMessageToTarget", - { - "targetId": workerId, - "message": JSON.stringify({ "method": method, - "params": params, - "id": workerRequestId++ }) - }); - } - - function didEnableWorkerDebugging(messageObject) - { - if ("error" in messageObject) { - InspectorTest.log("FAIL: Couldn't enable worker debugger: " + messageObject.error.message); - InspectorTest.completeTest(); - } - } - InspectorTest.sendCommand("Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: true}, didEnableWorkerDebugging); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "startWorker()" }); - - InspectorTest.eventHandler["Target.attachedToTarget"] = function(messageObject) - { - workerId = messageObject["params"]["targetInfo"]["targetId"]; - InspectorTest.log("Worker created"); - sendCommandToWorker("Debugger.enable", {}); - sendCommandToWorker("Runtime.runIfWaitingForDebugger", {}); - } - - var pauseCount = 0; - InspectorTest.eventHandler["Target.receivedMessageFromTarget"] = function(messageObject) - { - var message = JSON.parse(messageObject["params"]["message"]); - if (message["method"] === "Debugger.paused") { - InspectorTest.log("SUCCESS: Worker paused"); - if (++pauseCount === 1) { - InspectorTest.log("Stepping into..."); - sendCommandToWorker("Debugger.stepInto", {}); - } else { - sendCommandToWorker("Debugger.disable", {}); - InspectorTest.completeTest(); - } - } - } - -} -</script> -</head> -<body onLoad="runTest();"> -<p>Tests that dedicated worker won't crash on attempt to step into.<a href="https://code.google.com/p/chromium/issues/detail?id=232392">Bug 232392.</a> -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.js new file mode 100644 index 0000000..bfb43c7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.js
@@ -0,0 +1,41 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(`Tests that dedicated worker won't crash on attempt to step into.Bug 232392.`); + + var workerId; + var workerRequestId = 1; + function sendCommandToWorker(method, params) { + var message = {method, params, id: workerRequestId}; + dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); + return workerRequestId++; + } + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true}); + await session.evaluate(` + window.worker = new Worker('${testRunner.url('resources/dedicated-worker-step-into.js')}'); + window.worker.onmessage = function(event) { }; + window.worker.postMessage(1); + `); + testRunner.log('Started worker'); + + var messageObject = await dp.Target.onceAttachedToTarget(); + workerId = messageObject.params.targetInfo.targetId; + testRunner.log('Worker created'); + + sendCommandToWorker('Debugger.enable', {}); + sendCommandToWorker('Runtime.runIfWaitingForDebugger', {}); + + var pauseCount = 0; + dp.Target.onReceivedMessageFromTarget(async messageObject => { + var message = JSON.parse(messageObject.params.message); + if (message.method === 'Debugger.paused') { + testRunner.log('SUCCESS: Worker paused'); + if (++pauseCount === 1) { + testRunner.log('Stepping into...'); + sendCommandToWorker('Debugger.stepInto', {}); + } else { + sendCommandToWorker('Debugger.disable', {}); + testRunner.completeTest(); + } + } + }); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.html deleted file mode 100644 index 3919a0f..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.html +++ /dev/null
@@ -1,75 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - - -var worker; - -function startWorkerAndRunTest() -{ - worker = new Worker("resources/dedicated-worker.js"); - worker.onmessage = function(event) { }; - worker.postMessage(1); - log("Started worker"); - runTest(); -} - - -function test() -{ - - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) - { - InspectorTest.sendCommand("Target.sendMessageToTarget", - { - "targetId": workerId, - "message": JSON.stringify({ "method": method, - "params": params, - "id": workerRequestId++ }) - }); - } - - function didEnableWorkerDebugging(messageObject) - { - if ("error" in messageObject) { - InspectorTest.log("FAIL: Couldn't enable worker debugger: " + messageObject.error.message); - InspectorTest.completeTest(); - } - } - InspectorTest.sendCommand("Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: false}, didEnableWorkerDebugging); - - - InspectorTest.eventHandler["Target.attachedToTarget"] = function(messageObject) - { - workerId = messageObject["params"]["targetInfo"]["targetId"]; - InspectorTest.log("Worker created"); - InspectorTest.log("didConnectToWorker"); - sendCommandToWorker("Debugger.enable", {}); - sendCommandToWorker("Debugger.pause", {}); - } - - InspectorTest.eventHandler["Target.receivedMessageFromTarget"] = function(messageObject) - { - var message = JSON.parse(messageObject["params"]["message"]); - if (message["method"] === "Debugger.paused") { - InspectorTest.log("Worker paused"); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "worker.terminate()" }, didTerminateWorker); - } - } - - function didTerminateWorker(messageObject) - { - InspectorTest.log("SUCCESS: Did terminate paused worker"); - InspectorTest.completeTest(); - } - -} -</script> -</head> -<body onLoad="startWorkerAndRunTest();">Test that inspected page won't crash if inspected worker is terminated while it is paused. Test passes if it doesn't crash. -<a href="https://bugs.webkit.org/show_bug.cgi?id=101065">Bug 101065.</a> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.js new file mode 100644 index 0000000..9c7bf596 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.js
@@ -0,0 +1,37 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank( + `Test that inspected page won't crash if inspected worker is terminated while it is paused. Test passes if it doesn't crash. Bug 101065.`); + + await session.evaluate(` + window.worker = new Worker('${testRunner.url('resources/dedicated-worker.js')}'); + window.worker.onmessage = function(event) { }; + window.worker.postMessage(1); + `); + testRunner.log('Started worker'); + + var workerRequestId = 1; + function sendCommandToWorker(method, params) { + var message = {method, params, id: workerRequestId}; + dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); + return workerRequestId++; + } + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + + var messageObject = await dp.Target.onceAttachedToTarget(); + var workerId = messageObject.params.targetInfo.targetId; + testRunner.log('Worker created'); + testRunner.log('didConnectToWorker'); + sendCommandToWorker('Debugger.enable', {}); + sendCommandToWorker('Debugger.pause', {}); + + dp.Target.onReceivedMessageFromTarget(async messageObject => { + var message = JSON.parse(messageObject.params.message); + if (message.method === 'Debugger.paused') { + testRunner.log('Worker paused'); + await dp.Runtime.evaluate({expression: 'worker.terminate()' }); + testRunner.log('SUCCESS: Did terminate paused worker'); + testRunner.completeTest(); + } + }); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners-expected.txt index c2d3373..231a947 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners-expected.txt
@@ -1,3 +1,4 @@ + Event listeners of window type:click useCapture:true @@ -15,14 +16,6 @@ handler.className:Function handler.description:function hoverHandler(event) { console.log("hover - button - bubbling"); } - type:load - useCapture:false - lineNumber:164 - columnNumber:18 - handler.type:function - handler.className:Function - handler.description:function onload(event) { runTest();} - type:scroll useCapture:false lineNumber:1 @@ -59,8 +52,8 @@ type:load useCapture:false - lineNumber:162 - columnNumber:33 + lineNumber:0 + columnNumber:38 handler.type:function handler.className:Function handler.description:function onload(event) { return 42;}
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners.html deleted file mode 100644 index 856dfc7..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners.html +++ /dev/null
@@ -1,167 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function test() -{ - // A general-purpose engine for sending a sequence of protocol commands. - // The clients provide requests and response handlers, while the engine catches - // errors and makes sure that once there's nothing to do completeTest() is called. - // @param step is an object with command, params and callback fields. - function runRequestSeries(step) - { - processStep(step); - - function processStep(s) - { - try { - processStepOrFail(s); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - } - } - - function processStepOrFail(s) - { - if (!s) { - InspectorTest.completeTest(); - return; - } - if (!s.command) { - // A simple loopback step. - var next = s.callback(); - processStep(next); - return; - } - - var innerCallback = function(response) - { - if ("error" in response) { - InspectorTest.log(response.error.message); - InspectorTest.completeTest(); - return; - } - var next; - try { - next = s.callback(response.result); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - return; - } - processStep(next); - } - InspectorTest.sendCommand(s.command, s.params, innerCallback); - } - } - - runRequestSeries({ callback: callbackStartWindow }); - - function callbackStartWindow() - { - var expression = "(function(){\n\ - window.addEventListener('scroll', function(){ consol.log(42) }, false);\n\ - window.addEventListener('scroll', function(){ consol.log(42) }, false);\n\ - function clickHandler(event) { console.log('click - button - bubbling (registered before attribute)'); }\n\ - window.addEventListener(\"click\", clickHandler, true);\n\ - window.addEventListener(\"hover\", function hoverHandler(event) { console.log(\"hover - button - bubbling\"); }, true);\n\ - return window;\n\ - })()"; - return { command: "Runtime.evaluate", params: {expression: expression, objectGroup: "event-listeners-test"}, callback: callbackEvalWindow }; - } - function callbackEvalWindow(result) - { - var id = result.result.objectId; - if (id === undefined) - throw new Error("objectId is expected"); - return { - command: "DOMDebugger.getEventListeners", params: {objectId: id}, callback: callbackListenersWindow - }; - } - function callbackListenersWindow(result) - { - logGetListenersResult("window", result); - return {callback: calbackStartDivWithListeners}; - } - - function calbackStartDivWithListeners() - { - var expression = "(function(){\n\ - var div = document.getElementById(\"listeners1\");\n\ - function clickHandler(event) { console.log('click - button - bubbling (registered before attribute)'); }\n\ - div.addEventListener(\"click\", clickHandler, true);\n\ - div.addEventListener(\"hover\", function hoverHandler(event) { console.log(\"hover - button - bubbling\"); }, true);\n\ - return div;\n\ - })()"; - return { command: "Runtime.evaluate", params: {expression: expression, objectGroup: "event-listeners-test"}, callback: callbackEvalDivWithListeners }; - } - function callbackEvalDivWithListeners(result) - { - var id = result.result.objectId; - if (id === undefined) - throw new Error("objectId is expected"); - return { - command: "DOMDebugger.getEventListeners", params: {objectId: id}, callback: callbackListenersDivWithListeners - }; - } - function callbackListenersDivWithListeners(result) - { - logGetListenersResult("div#listeners1", result); - return {callback: calbackStartDivWithoutListeners}; - } - - function calbackStartDivWithoutListeners() - { - var expression = "(function(){\n\ - return document.getElementById(\"listeners2\");\n\ - })()"; - return { command: "Runtime.evaluate", params: {expression: expression, objectGroup: "event-listeners-test"}, callback: callbackEvalDivWithoutListeners }; - } - function callbackEvalDivWithoutListeners(result) - { - var id = result.result.objectId; - if (id === undefined) - throw new Error("objectId is expected"); - return { - command: "DOMDebugger.getEventListeners", params: {objectId: id}, callback: callbackListenersDivWithoutListeners - }; - } - function callbackListenersDivWithoutListeners(result) - { - logGetListenersResult("div#listeners2", result); - } - - function logGetListenersResult(title, protocolResult) - { - InspectorTest.log("Event listeners of " + title); - var listenersArray = protocolResult.listeners; - listenersArray.sort(TypedThingComparator); - for (var i = 0; i < listenersArray.length; i++) { - var l = listenersArray[i]; - InspectorTest.log(" type:" + l.type); - InspectorTest.log(" useCapture:" + l.useCapture); - InspectorTest.log(" lineNumber:" + l.lineNumber); - InspectorTest.log(" columnNumber:" + l.columnNumber); - if (l.handler) { - InspectorTest.log(" handler.type:" + l.handler.type); - InspectorTest.log(" handler.className:" + l.handler.className); - InspectorTest.log(" handler.description:" + l.handler.description.replace(/(\r\n|\n|\r)/gm,"")); - } - InspectorTest.log(""); - } - InspectorTest.log(""); - function TypedThingComparator(o1, o2) - { - return o1.type === o2.type ? 0 : (o1.type < o2.type ? -1 : 1); - } - } -} -</script> -</head> -<div id="listeners1" onload="return 42;"></div> -<div id="listeners2"></div> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners.js new file mode 100644 index 0000000..3a7b1dd2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-getEventListeners.js
@@ -0,0 +1,57 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startHTML(` + <div id='listeners1' onload='return 42;'></div> + <div id='listeners2'></div> + `, ``); + + function logGetListenersResult(title, response) { + testRunner.log('Event listeners of ' + title); + var listenersArray = response.result.listeners; + listenersArray.sort((o1, o2) => o1.type === o2.type ? 0 : (o1.type < o2.type ? -1 : 1)); + for (var l of listenersArray) { + testRunner.log(' type:' + l.type); + testRunner.log(' useCapture:' + l.useCapture); + testRunner.log(' lineNumber:' + l.lineNumber); + testRunner.log(' columnNumber:' + l.columnNumber); + if (l.handler) { + testRunner.log(' handler.type:' + l.handler.type); + testRunner.log(' handler.className:' + l.handler.className); + testRunner.log(' handler.description:' + l.handler.description.replace(/(\r\n|\n|\r)/gm,'')); + } + testRunner.log(''); + } + testRunner.log(''); + } + + var objectId = (await dp.Runtime.evaluate({expression: + `(function(){ + window.addEventListener('scroll', function(){ consol.log(42) }, false); + window.addEventListener('scroll', function(){ consol.log(42) }, false); + function clickHandler(event) { console.log('click - button - bubbling (registered before attribute)'); } + window.addEventListener('click', clickHandler, true); + window.addEventListener('hover', function hoverHandler(event) { console.log("hover - button - bubbling"); }, true); + return window; + })() + `, objectGroup: 'event-listeners-test'})).result.result.objectId; + logGetListenersResult('window', await dp.DOMDebugger.getEventListeners({objectId})); + + var objectId = (await dp.Runtime.evaluate({expression: + `(function(){ + var div = document.getElementById('listeners1'); + function clickHandler(event) { console.log('click - button - bubbling (registered before attribute)'); } + div.addEventListener('click', clickHandler, true); + div.addEventListener('hover', function hoverHandler(event) { console.log("hover - button - bubbling"); }, true); + return div; + })() + `, objectGroup: 'event-listeners-test'})).result.result.objectId; + logGetListenersResult('div#listeners1', await dp.DOMDebugger.getEventListeners({objectId})); + + var objectId = (await dp.Runtime.evaluate({expression: + `(function(){ + return document.getElementById('listeners2'); + })() + `, objectGroup: 'event-listeners-test'})).result.result.objectId; + logGetListenersResult('div#listeners2', await dp.DOMDebugger.getEventListeners({objectId})); + + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp-expected.txt index 0c0a485..a6902f5 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp-expected.txt
@@ -1,10 +1,4 @@ -CONSOLE ERROR: line 2: Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. -CONSOLE ERROR: line 4: Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-bhHHL3z2vDgxUt0W3dWQOrprscmda2Y5pLsLg4GF+pI='), or a nonce ('nonce-...') is required to enable inline execution. - -CONSOLE ERROR: line 5: Refused to execute JavaScript URL because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. - -Button ------- blockedEventHandler
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp.html deleted file mode 100644 index 1fb01011..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp.html +++ /dev/null
@@ -1,10 +0,0 @@ -<html> -<head> -<meta http-equiv="Content-Security-Policy" content="script-src 'self';"> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script type="text/javascript" src="resources/script-blocked-by-csp.js"></script> -</head> -<body> -<button id="testButton" onclick="alert(1);">Button</button> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp.js new file mode 100644 index 0000000..8f700db --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-script-blocked-by-csp.js
@@ -0,0 +1,55 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startHTML(` + <html> + <head> + <meta http-equiv='Content-Security-Policy' content="script-src 'self';"> + </head> + <body> + <button id='testButton' onclick='alert(1);'>Button</button> + </body> + </html> + `, ``); + + dp.Debugger.enable(); + dp.DOM.enable(); + dp.DOMDebugger.enable(); + dp.DOMDebugger.setInstrumentationBreakpoint({eventName: 'scriptBlockedByCSP'}); + + var expressions = [ + ` + document.getElementById('testButton').click(); + `, + + ` + var script = document.createElement('script'); + script.innerText = 'alert(1)'; + document.body.appendChild(script); + `, + + ` + var a = document.createElement('a'); + a.setAttribute('href', 'javascript:alert(1);'); + var dummy = 1; + document.body.appendChild(a); a.click(); + ` + ]; + var descriptions = [ + 'blockedEventHandler', + 'blockedScriptInjection', + 'blockedScriptUrl' + ]; + + for (var i = 0; i < expressions.length; i++) { + var funcName = descriptions[i]; + testRunner.log('\n-------\n' + funcName); + dp.Runtime.evaluate({expression: 'function ' + funcName + '() {' + expressions[i] + '}\n' + funcName + '()'}); + var messageObject = await dp.Debugger.oncePaused(); + var params = messageObject.params; + testRunner.log('Paused at: ' + params.callFrames[0].functionName + '@' + params.callFrames[0].location.lineNumber); + testRunner.log('Reason: ' + params.reason + '; Data:'); + testRunner.logObject(params.data); + await dp.Debugger.resume(); + } + + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-expected.txt index a97b8e52..4dce98314 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-expected.txt
@@ -1,3 +1,3 @@ -innerHTML + Paused on the innerHTML assignment: modifyHTML@:7
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML.html deleted file mode 100644 index bb8c99d63..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML.html +++ /dev/null
@@ -1,36 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function modifyHTML() -{ - document.getElementById("divUnderTest").innerHTML = "innerHTML"; -} - -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}); - InspectorTest.sendCommand("DOM.enable", {}); - InspectorTest.sendCommand("DOMDebugger.enable", {}); - InspectorTest.sendCommand("DOMDebugger.setInstrumentationBreakpoint", {"eventName":"Element.setInnerHTML"}); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "modifyHTML()" }); - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedOne; - - function handleDebuggerPausedOne(messageObject) - { - var callFrame = messageObject.params.callFrames[0]; - InspectorTest.log("Paused on the innerHTML assignment: " + callFrame.functionName + "@:" + callFrame.location.lineNumber); - InspectorTest.sendCommand("Debugger.resume", { }, didResume); - function didResume() - { - InspectorTest.completeTest(); - } - } -} -</script> -</head> -<body onLoad="runTest();"> -<div id="divUnderTest"></div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML.js new file mode 100644 index 0000000..486242e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML.js
@@ -0,0 +1,25 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startHTML(` + <div id='divUnderTest'></div> + `, ``); + + dp.Debugger.enable(); + dp.DOM.enable(); + dp.DOMDebugger.enable(); + dp.DOMDebugger.setInstrumentationBreakpoint({eventName: 'Element.setInnerHTML'}); + dp.Runtime.evaluate({expression: ` + + + + + + (function modifyHTML() { + document.getElementById('divUnderTest').innerHTML = 'innerHTML'; + })() + ` }); + var messageObject = await dp.Debugger.oncePaused(); + var callFrame = messageObject.params.callFrames[0]; + testRunner.log('Paused on the innerHTML assignment: ' + callFrame.functionName + '@:' + callFrame.location.lineNumber); + await dp.Debugger.resume(); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause-expected.txt index 568693f..96cf4515 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause-expected.txt
@@ -1,3 +1,4 @@ + Paused on 'debugger;' PASS: message has not been dispatched yet. PASS: message has not been dispatched yet.
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause.html deleted file mode 100644 index 7cb5fbc..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause.html +++ /dev/null
@@ -1,72 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -var messageDispatched = false; -window.addEventListener("message", function(event) -{ - messageDispatched = true; - debugger; -}, true); - -function testFunction() -{ - window.postMessage("test", "*"); - debugger; -} - -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}); - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedInTestFunction; - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "testFunction()" }); - - function handleDebuggerPausedInTestFunction(messageObject) - { - InspectorTest.log("Paused on 'debugger;'"); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "messageDispatched" }, didEvaluateOnPause1); - } - - function didEvaluateOnPause1(messageObject) - { - var r = messageObject.result.result; - if (r.type === "boolean" && r.value === false) - InspectorTest.log("PASS: message has not been dispatched yet."); - else - InspectorTest.log("FAIL: unexpected response " + JSON.stringify(messageObject, null, 2)); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "messageDispatched" }, didEvaluateOnPause2); - } - - function didEvaluateOnPause2(messageObject) - { - var r = messageObject.result.result; - if (r.type === "boolean" && r.value === false) - InspectorTest.log("PASS: message has not been dispatched yet."); - else - InspectorTest.log("FAIL: unexpected response " + JSON.stringify(messageObject, null, 2)); - InspectorTest.sendCommand("Debugger.resume", { }, didResume); - } - - function didResume(messageObject) - { - InspectorTest.log("Resumed, now waiting for pause in the event listener..."); - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPausedInEventListener; - } - - function handleDebuggerPausedInEventListener(messageObject) - { - InspectorTest.log("PASS: pasued in the event listener."); - InspectorTest.sendCommand("Debugger.resume", { }, didResume2); - } - - function didResume2(messageObject) - { - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause.js new file mode 100644 index 0000000..6a2b7b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/postMessage-on-pause.js
@@ -0,0 +1,42 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + dp.Debugger.enable(); + dp.Runtime.evaluate({expression: ` + var messageDispatched = false; + window.addEventListener('message', event => { + messageDispatched = true; + debugger; + }, true); + + (function testFunction() { + window.postMessage('test', '*'); + debugger; + })() + `}); + + await dp.Debugger.oncePaused(); + testRunner.log(`Paused on 'debugger;'`); + + var messageObject = await dp.Runtime.evaluate({expression: 'messageDispatched' }); + var r = messageObject.result.result; + if (r.type === 'boolean' && r.value === false) + testRunner.log('PASS: message has not been dispatched yet.'); + else + testRunner.log('FAIL: unexpected response ' + JSON.stringify(messageObject, null, 2)); + + messageObject = await dp.Runtime.evaluate({expression: 'messageDispatched' }); + r = messageObject.result.result; + if (r.type === 'boolean' && r.value === false) + testRunner.log('PASS: message has not been dispatched yet.'); + else + testRunner.log('FAIL: unexpected response ' + JSON.stringify(messageObject, null, 2)); + + await dp.Debugger.resume(); + testRunner.log('Resumed, now waiting for pause in the event listener...'); + + await dp.Debugger.oncePaused(); + testRunner.log('PASS: pasued in the event listener.'); + await dp.Debugger.resume(); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/blackboxed.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/blackboxed.js deleted file mode 100644 index 51da71a..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/blackboxed.js +++ /dev/null
@@ -1,7 +0,0 @@ -function blackboxedBoo() -{ - var a = 42; - var b = foo(); - return a + b; -} -//# sourceURL=blackboxed-script.js
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/mixed.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/mixed.js deleted file mode 100644 index df01a0e9..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/mixed.js +++ /dev/null
@@ -1,21 +0,0 @@ -function notBlackboxedFoo() -{ - var a = 42; - var b = blackboxedBoo(); - return a + b; -} - -function blackboxedFoo() -{ - var a = 42; - var b = notBlackboxedFoo(); - return a + b; -} - -function notBlackboxedBoo() -{ - var a = 42; - var b = blackboxedFoo(); - return a + b; -} -//# sourceURL=mixed-source.js
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/script-blocked-by-csp.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/script-blocked-by-csp.js deleted file mode 100644 index 31a5ce5..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/script-blocked-by-csp.js +++ /dev/null
@@ -1,50 +0,0 @@ -function test() -{ - InspectorTest.sendCommand("Debugger.enable", {}); - InspectorTest.sendCommand("DOM.enable", {}); - InspectorTest.sendCommand("DOMDebugger.enable", {}); - InspectorTest.sendCommand("DOMDebugger.setInstrumentationBreakpoint", {"eventName":"scriptBlockedByCSP"}); - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPaused; - - var expressions = [ - "\n document.getElementById('testButton').click();", - - "\n var script = document.createElement('script');" + - "\n script.innerText = 'alert(1)';" + - "\n document.body.appendChild(script);", - - "\n var a = document.createElement('a');" + - "\n a.setAttribute('href', 'javascript:alert(1);');" + - "\n var dummy = 1; " + - "\n document.body.appendChild(a); a.click();" - ]; - var descriptions = [ - "blockedEventHandler", - "blockedScriptInjection", - "blockedScriptUrl" - ]; - - function nextExpression() - { - if (!expressions.length) { - InspectorTest.completeTest(); - return; - } - var description = descriptions.shift(); - InspectorTest.log("\n-------\n" + description); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "function " + description + "() {" + expressions.shift() + "}\n" + description + "()"}); - } - - function handleDebuggerPaused(messageObject) - { - var params = messageObject.params; - InspectorTest.log("Paused at: " + params.callFrames[0].functionName + "@" + params.callFrames[0].location.lineNumber); - InspectorTest.log("Reason: " + params.reason + "; Data:"); - InspectorTest.logObject(params.data); - InspectorTest.sendCommand("Debugger.resume", { }, nextExpression); - } - - nextExpression(); -} - -window.addEventListener("load", runTest.bind(null, false));
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/statements.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/statements.js deleted file mode 100644 index cec8a12..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/resources/statements.js +++ /dev/null
@@ -1,19 +0,0 @@ -function statementsExample() -{ - var self = arguments.callee; - - debugger; - - self.step = 1; - - self.step = 2; - - void [ - self.step = 3, - self.step = 4, - self.step = 5, - self.step = 6 - ]; - - self.step = 7; -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash-expected.txt index 237f325..b5a0f54 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash-expected.txt
@@ -1,3 +1,4 @@ + Hash received: 1C6D2E82E4E4F1BA4CB5762843D429DC872EBA18 Hash received: EBF1ECD351E7A3294CB5762843D429DC872EBA18 Hash received: 22D0043331237371241FC675A984B967025A3DC0
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash.html deleted file mode 100644 index d441cb1..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash.html +++ /dev/null
@@ -1,37 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> -function test() -{ - var hashes = new Set(["1C6D2E82E4E4F1BA4CB5762843D429DC872EBA18", - "EBF1ECD351E7A3294CB5762843D429DC872EBA18", - "22D0043331237371241FC675A984B967025A3DC0"]); - InspectorTest.sendCommandOrDie("Debugger.enable", {}, function() { - InspectorTest.eventHandler["Debugger.scriptParsed"] = function(messageObject) - { - if (hashes.has(messageObject.params.hash)) - InspectorTest.log("Hash received: " + messageObject.params.hash); - } - }); - - function longScript() { - var longScript = "var b = 1;"; - for (var i = 0; i < 2024; ++i) - longScript += "++b;"; - } - - InspectorTest.sendCommandOrDie("Runtime.evaluate", { expression: "1" }); - InspectorTest.sendCommandOrDie("Runtime.evaluate", { expression: "239" }); - InspectorTest.sendCommandOrDie("Runtime.evaluate", { expression: "(" + longScript + ")()" }, step2); - - function step2() - { - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash.js new file mode 100644 index 0000000..8e5db35c --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/scriptParsedHash.js
@@ -0,0 +1,24 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + var hashes = new Set(['1C6D2E82E4E4F1BA4CB5762843D429DC872EBA18', + 'EBF1ECD351E7A3294CB5762843D429DC872EBA18', + '22D0043331237371241FC675A984B967025A3DC0']); + + dp.Debugger.enable(); + dp.Debugger.onScriptParsed(messageObject => { + if (hashes.has(messageObject.params.hash)) + testRunner.log('Hash received: ' + messageObject.params.hash); + }); + + function longScript() { + var longScript = "var b = 1;"; + for (var i = 0; i < 2024; ++i) + longScript += "++b;"; + } + + dp.Runtime.evaluate({expression: '1'}); + dp.Runtime.evaluate({expression: '239'}); + await dp.Runtime.evaluate({expression: '(' + longScript + ')()' }); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt index 1b76ec5..9e355e2 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt
@@ -1,3 +1,4 @@ + Function evaluate: {"type":"number","value":6,"description":"6"} PASS, result value: 6 Function evaluate: {"type":"number","value":8,"description":"8"}
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html deleted file mode 100644 index 9bdb671..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html +++ /dev/null
@@ -1,156 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script type="text/javascript" src="resources/liveedit-me.js"></script> -<script> - -function test() -{ - // A general-purpose engine for sending a sequence of protocol commands. - // The clients provide requests and response handlers, while the engine catches - // errors and makes sure that once there's nothing to do completeTest() is called. - // @param step is an object with command, params and callback fields - function runRequestSeries(step) { - processStep(step); - - function processStep(currentStep) { - try { - processStepOrFail(currentStep); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - } - } - - function processStepOrFail(currentStep) { - if (!currentStep) { - InspectorTest.completeTest(); - return; - } - if (!currentStep.command) { - // A simple loopback step. - var next = currentStep.callback(); - processStep(next); - return; - } - - var innerCallback = function(response) { - var next; - if ("error" in response) { - if (!("errorHandler" in currentStep)) { - // Error message is not logged intentionally, it may be platform-specific. - InspectorTest.log("Protocol command '" + currentStep.command + "' failed"); - InspectorTest.completeTest(); - return; - } - try { - next = currentStep.errorHandler(response.error); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - return; - } - } else { - try { - next = currentStep.callback(response.result); - } catch (e) { - InspectorTest.log(e.stack); - InspectorTest.completeTest(); - return; - } - } - processStep(next); - } - InspectorTest.sendCommand(currentStep.command, currentStep.params, innerCallback); - } - } - - function logEqualsCheck(actual, expected) - { - if (actual == expected) { - InspectorTest.log("PASS, result value: " + actual); - } else { - InspectorTest.log("FAIL, actual value: " + actual + ", expected: " + expected); - } - } - function logCheck(description, success) - { - InspectorTest.log(description + ": " + (success ? "PASS" : "FAIL")); - } - - var firstStep = { callback: enableDebugger }; - - runRequestSeries(firstStep); - - function enableDebugger() { - return { command: "Debugger.enable", params: {}, callback: evalFunction }; - } - - function evalFunction(response) { - var expression = "TestExpression(2, 4)"; - return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction }; - } - - function callbackEvalFunction(result) { - InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); - logEqualsCheck(result.result.value, 6); - - return { command: "Runtime.evaluate", params: { expression: "TestExpression" }, callback: callbackEvalFunctionObject }; - } - - function callbackEvalFunctionObject(result) { - return { command: "Runtime.getProperties", params: { objectId: result.result.objectId }, callback: callbackFunctionDetails }; - } - - function callbackFunctionDetails(result) - { - var scriptId; - for (var prop of result.internalProperties) { - if (prop.name === "[[FunctionLocation]]") - scriptId = prop.value.value.scriptId; - } - return createScriptManipulationArc(scriptId, null); - } - - // Several steps with scriptId in context. - function createScriptManipulationArc(scriptId, next) { - return { command: "Debugger.getScriptSource", params: { scriptId: scriptId }, callback: callbackGetScriptSource }; - - var originalText; - - function callbackGetScriptSource(result) { - originalText = result.scriptSource; - var patched = originalText.replace("a + b", "a * b"); - - return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: callbackSetScriptSource }; - } - - function callbackSetScriptSource(result) { - var expression = "TestExpression(2, 4)"; - return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction2 }; - } - - function callbackEvalFunction2(result) { - InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); - logEqualsCheck(result.result.value, 8); - - var patched = originalText.replace("a + b", "a # b"); - - return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: errorCallbackSetScriptSource2 }; - } - - function errorCallbackSetScriptSource2(result) { - var exceptionDetails = result.exceptionDetails; - logCheck("Has error reported", !!exceptionDetails); - logCheck("Reported error is a compile error", !!exceptionDetails); - if (exceptionDetails) - logEqualsCheck(exceptionDetails.lineNumber, 1); - return next; - } - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.js new file mode 100644 index 0000000..31b4f61 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.js
@@ -0,0 +1,46 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + function logEqualsCheck(actual, expected) { + if (actual == expected) { + testRunner.log('PASS, result value: ' + actual); + } else { + testRunner.log('FAIL, actual value: ' + actual + ', expected: ' + expected); + } + } + + await session.evaluate( + `function TestExpression(a, b) { + return a + b; + }`); + + await dp.Debugger.enable(); + + var response = await dp.Runtime.evaluate({expression: 'TestExpression(2, 4)' }); + testRunner.log('Function evaluate: ' + JSON.stringify(response.result.result)); + logEqualsCheck(response.result.result.value, 6); + + var functionObjectId = (await dp.Runtime.evaluate({expression: 'TestExpression' })).result.result.objectId; + var result = (await dp.Runtime.getProperties({ objectId: functionObjectId})).result; + var scriptId; + for (var prop of result.internalProperties) { + if (prop.name === '[[FunctionLocation]]') + scriptId = prop.value.value.scriptId; + } + + var originalText = (await dp.Debugger.getScriptSource({scriptId})).result.scriptSource; + var patched = originalText.replace('a + b', 'a * b'); + await dp.Debugger.setScriptSource({scriptId, scriptSource: patched}); + + var response = await dp.Runtime.evaluate({expression: 'TestExpression(2, 4)' }); + testRunner.log('Function evaluate: ' + JSON.stringify(response.result.result)); + logEqualsCheck(response.result.result.value, 8); + + patched = originalText.replace('a + b', 'a # b'); + var exceptionDetails = (await dp.Debugger.setScriptSource({scriptId, scriptSource: patched})).result.exceptionDetails; + testRunner.log(`Has error reported: ${!!exceptionDetails ? 'PASS' : 'FAIL'}`, ); + testRunner.log(`Reported error is a compile error: ${!!exceptionDetails ? 'PASS' : 'FAIL'}`, ); + if (exceptionDetails) + logEqualsCheck(exceptionDetails.lineNumber, 1); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.html deleted file mode 100644 index e120131..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.html +++ /dev/null
@@ -1,54 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function testFunction() -{ - var e = document.getElementById("div"); - debugger; - e.click(); -} - -function shouldNotBeThisFunction() -{ - return 239; -} - -function test() -{ - InspectorTest.waitForEventPromise("Debugger.paused").then(makeStepping); - - InspectorTest.sendCommandPromise("Debugger.enable", {}) - .then((result) => InspectorTest.sendCommandPromise("Runtime.evaluate", { expression: "testFunction()" })) - .then(() => InspectorTest.completeTest()); - - function makeStepping() - { - sendCommandAndWaitForPause("Debugger.stepInto") - .then(() => sendCommandAndWaitForPause("Debugger.stepInto")) - .then((result) => dumpTopCallFrame(result)) - .then(() => InspectorTest.sendCommandPromise("Debugger.resume")); - } - - function sendCommandAndWaitForPause(command) - { - InspectorTest.sendCommand(command, {}); - return InspectorTest.waitForEventPromise("Debugger.paused"); - } - - function dumpTopCallFrame(result) - { - var frame = result.params.callFrames[0]; - InspectorTest.log("functionName (should be empty): " + (frame.functionName.length ? frame.functionName : "empty")); - } -} -</script> -</head> -<div id="div" onclick="shouldNotBeThisFunction()"> -</div> -<body onLoad="runTest();"> -Tests that Debugger.stepInto doesn't ignore inline event listeners. -</body> -</html> -
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.js new file mode 100644 index 0000000..9d71b342 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.js
@@ -0,0 +1,35 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startHTML(` + <script> + function testFunction() { + var e = document.getElementById('div'); + debugger; + e.click(); + } + + function shouldNotBeThisFunction() { + return 239; + } + </script> + <div id='div' onclick='shouldNotBeThisFunction()'></div> + `, `Tests that Debugger.stepInto doesn't ignore inline event listeners.`); + + + function dumpTopCallFrame(result) { + var frame = result.params.callFrames[0]; + testRunner.log('functionName (should be empty): ' + (frame.functionName.length ? frame.functionName : 'empty')); + } + + await dp.Debugger.enable(); + var finished = dp.Runtime.evaluate({expression: 'testFunction()'}); + + await dp.Debugger.oncePaused(); + dp.Debugger.stepInto(); + await dp.Debugger.oncePaused(); + dp.Debugger.stepInto(); + dumpTopCallFrame(await dp.Debugger.oncePaused()); + dp.Debugger.resume(); + + await finished; + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception-expected.txt index 78aaf35..e6ce4af3 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception-expected.txt
@@ -1,5 +1,4 @@ -CONSOLE MESSAGE: line 16: completed -CONSOLE MESSAGE: line 16: completed + testFunction:13 testFunction:15 testFunction:13
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception.html deleted file mode 100644 index 1da33950..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception.html +++ /dev/null
@@ -1,83 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> -function testFunction() -{ - function foo() - { - try { - throw new Error(); - } catch (e) { - } - } - debugger; - foo(); - console.log("completed"); -} -</script> -<script> -function test() -{ - InspectorTest.sendCommandOrDie("Debugger.enable", {} ); - InspectorTest.sendCommandOrDie("Runtime.enable", {} ); - step1(); - - function step1() - { - InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "setTimeout(testFunction, 0);"} ); - var commands = [ "Print", "stepOver", "stepOver", "Print", "resume" ]; - InspectorTest.eventHandler["Debugger.paused"] = function(messageObject) - { - var command = commands.shift(); - if (command === "Print") { - var callFrames = messageObject.params.callFrames; - for (var callFrame of callFrames) - InspectorTest.log(callFrame.functionName + ":" + callFrame.location.lineNumber); - command = commands.shift(); - } - if (command) - InspectorTest.sendCommandOrDie("Debugger." + command, {}); - } - - InspectorTest.eventHandler["Runtime.consoleAPICalled"] = function(messageObject) - { - if (messageObject.params.args[0].value === "completed") { - if (commands.length) - InspectorTest.log("[FAIL]: execution was resumed too earlier.") - step2(); - } - } - } - - function step2() - { - InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "setTimeout(testFunction, 0);"} ); - var commands = [ "Print", "stepOver", "stepInto", "stepOver", "stepOver", "Print", "resume" ]; - InspectorTest.eventHandler["Debugger.paused"] = function(messageObject) - { - var command = commands.shift(); - if (command === "Print") { - var callFrames = messageObject.params.callFrames; - for (var callFrame of callFrames) - InspectorTest.log(callFrame.functionName + ":" + callFrame.location.lineNumber); - command = commands.shift(); - } - if (command) - InspectorTest.sendCommandOrDie("Debugger." + command, {}); - } - - InspectorTest.eventHandler["Runtime.consoleAPICalled"] = function(messageObject) - { - if (messageObject.params.args[0].value === "completed") { - if (commands.length) - InspectorTest.log("[FAIL]: execution was resumed too earlier.") - InspectorTest.completeTest(); - } - } - } -} -</script> -</head> -<body onLoad="runTest();"></body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception.js new file mode 100644 index 0000000..a30526d --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-over-caught-exception.js
@@ -0,0 +1,54 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + dp.Debugger.enable(); + dp.Runtime.enable(); + dp.Runtime.evaluate({expression: ` + + + + + + function testFunction() { + function foo() { + try { + throw new Error(); + } catch (e) { + } + } + debugger; + foo(); + console.log('completed'); + } + setTimeout(testFunction, 0); + `}); + + function printCallFrames(messageObject) { + var callFrames = messageObject.params.callFrames; + for (var callFrame of callFrames) + testRunner.log(callFrame.functionName + ':' + callFrame.location.lineNumber); + } + + printCallFrames(await dp.Debugger.oncePaused()); + dp.Debugger.stepOver(); + await dp.Debugger.oncePaused(); + dp.Debugger.stepOver(); + printCallFrames(await dp.Debugger.oncePaused()); + dp.Debugger.resume(); + await dp.Runtime.onceConsoleAPICalled(messageObject => messageObject.params.args[0].value === 'completed'); + + dp.Runtime.evaluate({expression: 'setTimeout(testFunction, 0);'} ); + printCallFrames(await dp.Debugger.oncePaused()); + dp.Debugger.stepOver(); + await dp.Debugger.oncePaused(); + dp.Debugger.stepInto(); + await dp.Debugger.oncePaused(); + dp.Debugger.stepOver(); + await dp.Debugger.oncePaused(); + dp.Debugger.stepOver(); + printCallFrames(await dp.Debugger.oncePaused()); + dp.Debugger.resume(); + await dp.Runtime.onceConsoleAPICalled(messageObject => messageObject.params.args[0].value === 'completed'); + + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt index 2969deb4..10cc9e4 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges-expected.txt
@@ -1,3 +1,4 @@ + foo: 14:4 blackboxedBoo: 3:12 notBlackboxedFoo: 3:12
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges.html deleted file mode 100644 index cbb17ec..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges.html +++ /dev/null
@@ -1,104 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script type="text/javascript" src="resources/blackboxed.js"></script> -<script type="text/javascript" src="resources/mixed.js"></script> -<script> -function testFunction() -{ - notBlackboxedBoo(); // for setup ranges and stepOut - notBlackboxedBoo(); // for stepIn -} - -function foo() -{ - debugger; - return 239; -} -</script> -<script> -function test() -{ - InspectorTest.eventHandler["Debugger.paused"] = setBlackboxedScriptRanges; - InspectorTest.sendCommandOrDie("Debugger.enable", {}, callTestFunction); - - function callTestFunction(response) - { - InspectorTest.evaluateInInspectedPage("setTimeout(testFunction, 0);"); - } - - function setBlackboxedScriptRanges(response) - { - var callFrames = response.params.callFrames; - printCallFrames(callFrames); - InspectorTest.sendCommand("Debugger.setBlackboxedRanges", { - scriptId: callFrames[1].location.scriptId, - positions: [ { lineNumber: 0, columnNumber: 0 } ] // blackbox ranges for blackboxed.js - }, setIncorrectRanges.bind(null, callFrames[2].location.scriptId)); - } - - var incorrectPositions = [ - [ { lineNumber: 0, columnNumber: 0 }, { lineNumber: 0, columnNumber: 0 } ], - [ { lineNumber: 0, columnNumber: 1 }, { lineNumber: 0, columnNumber: 0 } ], - [ { lineNumber: 0, columnNumber: -1 } ], - ]; - - function setIncorrectRanges(scriptId, response) - { - if (response.error) - InspectorTest.log(response.error.message); - var positions = incorrectPositions.shift(); - if (!positions) { - setMixedSourceRanges(scriptId); - return; - } - InspectorTest.log("Try to set positions: " + JSON.stringify(positions)); - InspectorTest.sendCommand("Debugger.setBlackboxedRanges", { - scriptId: scriptId, - positions: positions - }, setIncorrectRanges.bind(null, scriptId)); - } - - function setMixedSourceRanges(scriptId) - { - InspectorTest.eventHandler["Debugger.paused"] = runAction; - InspectorTest.sendCommandOrDie("Debugger.setBlackboxedRanges", { - scriptId: scriptId, - positions: [ { lineNumber: 6, columnNumber: 0 }, { lineNumber: 14, columnNumber: 0 } ] // blackbox ranges for mixed.js - }, runAction); - } - - var actions = [ "stepOut", "print", "stepOut", "print", "stepOut", "print", - "stepInto", "print", "stepOver", "stepInto", "print", "stepOver", "stepInto", "print", - "stepOver", "stepInto", "print" ]; - - function runAction(response) - { - var action = actions.shift(); - if (!action) - InspectorTest.completeTest(); - - if (action === "print") { - printCallFrames(response.params.callFrames); - runAction({}); - } else { - InspectorTest.log("action: " + action); - InspectorTest.sendCommandOrDie("Debugger." + action, {}); - } - } - - function printCallFrames(callFrames) - { - var topCallFrame = callFrames[0]; - if (topCallFrame.functionName.startsWith("blackboxed")) - InspectorTest.log("FAIL: blackboxed function in top call frame"); - for (var callFrame of callFrames) - InspectorTest.log(callFrame.functionName + ': ' + callFrame.location.lineNumber + ":" + callFrame.location.columnNumber); - InspectorTest.log(""); - } -} -</script> -</head> -<body onload="runTest()"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges.js new file mode 100644 index 0000000..49757284 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/stepping-with-blackboxed-ranges.js
@@ -0,0 +1,131 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + function printCallFrames(response) { + var callFrames = response.params.callFrames; + var topCallFrame = callFrames[0]; + if (topCallFrame.functionName.startsWith('blackboxed')) + testRunner.log('FAIL: blackboxed function in top call frame'); + for (var callFrame of callFrames) + testRunner.log(callFrame.functionName + ': ' + callFrame.location.lineNumber + ':' + callFrame.location.columnNumber); + testRunner.log(''); + } + + function printError(response) { + if (response.error) + testRunner.log(response.error.message); + } + + await session.evaluate( +`function blackboxedBoo() +{ + var a = 42; + var b = foo(); + return a + b; +} +//# sourceURL=blackboxed-script.js +`); + + await session.evaluate( +`function notBlackboxedFoo() +{ + var a = 42; + var b = blackboxedBoo(); + return a + b; +} + +function blackboxedFoo() +{ + var a = 42; + var b = notBlackboxedFoo(); + return a + b; +} + +function notBlackboxedBoo() +{ + var a = 42; + var b = blackboxedFoo(); + return a + b; +} +//# sourceURL=mixed-source.js +`); + + await session.evaluate(` + + + + + +function testFunction() +{ + notBlackboxedBoo(); // for setup ranges and stepOut + notBlackboxedBoo(); // for stepIn +} + +function foo() +{ + debugger; + return 239; +} + `); + + await dp.Debugger.enable(); + session.evaluate('setTimeout(testFunction, 0);'); + + var response = await dp.Debugger.oncePaused(); + printCallFrames(response); + var scriptId = response.params.callFrames[2].location.scriptId; + + printError(await dp.Debugger.setBlackboxedRanges({ + scriptId: response.params.callFrames[1].location.scriptId, + positions: [{lineNumber: 0, columnNumber: 0}] // blackbox ranges for blackboxed.js + })); + + var incorrectPositions = [ + [{lineNumber: 0, columnNumber: 0}, {lineNumber: 0, columnNumber: 0}], + [{lineNumber: 0, columnNumber: 1}, {lineNumber: 0, columnNumber: 0}], + [{lineNumber: 0, columnNumber: -1}], + ]; + for (var positions of incorrectPositions) { + testRunner.log('Try to set positions: ' + JSON.stringify(positions)); + printError(await dp.Debugger.setBlackboxedRanges({scriptId, positions})); + } + + await dp.Debugger.setBlackboxedRanges({ + scriptId, + positions: [{lineNumber: 6, columnNumber: 0}, {lineNumber: 14, columnNumber: 0}] // blackbox ranges for mixed.js + }); + + testRunner.log('action: stepOut'); + dp.Debugger.stepOut(); + printCallFrames(await dp.Debugger.oncePaused()); + testRunner.log('action: stepOut'); + dp.Debugger.stepOut(); + printCallFrames(await dp.Debugger.oncePaused()); + testRunner.log('action: stepOut'); + dp.Debugger.stepOut(); + printCallFrames(await dp.Debugger.oncePaused()); + testRunner.log('action: stepInto'); + dp.Debugger.stepInto(); + printCallFrames(await dp.Debugger.oncePaused()); + testRunner.log('action: stepOver'); + dp.Debugger.stepOver(); + await dp.Debugger.oncePaused(); + testRunner.log('action: stepInto'); + dp.Debugger.stepInto(); + printCallFrames(await dp.Debugger.oncePaused()); + testRunner.log('action: stepOver'); + dp.Debugger.stepOver(); + await dp.Debugger.oncePaused(); + testRunner.log('action: stepInto'); + dp.Debugger.stepInto(); + printCallFrames(await dp.Debugger.oncePaused()); + testRunner.log('action: stepOver'); + dp.Debugger.stepOver(); + await dp.Debugger.oncePaused(); + testRunner.log('action: stepInto'); + dp.Debugger.stepInto(); + printCallFrames(await dp.Debugger.oncePaused()); + await dp.Debugger.resume(); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt index d6da87d7..492170a 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt
@@ -1,5 +1,4 @@ Tests that setTimeout callback will not fire while script execution is paused.Bug 377926. - Started worker Worker created SUCCESS: Worker paused
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.html deleted file mode 100644 index 7853e5d..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.html +++ /dev/null
@@ -1,82 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> -var worker; - -function startWorker() -{ - worker = new Worker("resources/dedicated-worker-suspend-setTimeout.js"); - worker.onmessage = function(event) { }; - worker.postMessage(1); - log("Started worker"); -} - - -function test() -{ - - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) - { - var requestId = workerRequestId++; - InspectorTest.sendCommand("Target.sendMessageToTarget", - { - "targetId": workerId, - "message": JSON.stringify({ "method": method, - "params": params, - "id": requestId }) - }); - return requestId; - } - - function didEnableWorkerDebugging(messageObject) - { - if ("error" in messageObject) { - InspectorTest.log("FAIL: Couldn't enable worker debugger: " + messageObject.error.message); - InspectorTest.completeTest(); - } - } - InspectorTest.sendCommand("Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: true}, didEnableWorkerDebugging); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "startWorker()" }); - - InspectorTest.eventHandler["Target.attachedToTarget"] = function(messageObject) - { - workerId = messageObject["params"]["targetInfo"]["targetId"]; - InspectorTest.log("Worker created"); - sendCommandToWorker("Debugger.enable", {}); - sendCommandToWorker("Runtime.runIfWaitingForDebugger", {}); - } - - var pauseCount = 0; - var evalRequestId; - InspectorTest.eventHandler["Target.receivedMessageFromTarget"] = function(messageObject) - { - var message = JSON.parse(messageObject["params"]["message"]); - if (message["method"] === "Debugger.paused") { - InspectorTest.log("SUCCESS: Worker paused"); - if (++pauseCount === 1) { - evalRequestId = sendCommandToWorker("Runtime.evaluate", { "expression": "global_value" }); - } else { - InspectorTest.log("FAIL: debugger paused second time"); - InspectorTest.completeTest(); - } - } else if (evalRequestId && message["id"] === evalRequestId) { - var value = message["result"]["result"]["value"]; - if (value === 1) - InspectorTest.log("SUCCESS: global_value is 1"); - else - InspectorTest.log("FAIL: setTimeout callback fired while script execution was paused"); - sendCommandToWorker("Debugger.disable", {}); - InspectorTest.completeTest(); - } - } -} -</script> -</head> -<body onLoad="runTest();"> -<p>Tests that setTimeout callback will not fire while script execution is paused.<a href="https://code.google.com/p/chromium/issues/detail?id=377926">Bug 377926.</a> -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js new file mode 100644 index 0000000..f5ffb967 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js
@@ -0,0 +1,49 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank('Tests that setTimeout callback will not fire while script execution is paused.Bug 377926.'); + + var workerId; + var workerRequestId = 1; + function sendCommandToWorker(method, params) { + var message = {method, params, id: workerRequestId}; + dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); + return workerRequestId++; + } + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true}); + await session.evaluate(` + window.worker = new Worker('${testRunner.url('resources/dedicated-worker-suspend-setTimeout.js')}'); + window.worker.onmessage = function(event) { }; + window.worker.postMessage(1); + `); + testRunner.log('Started worker'); + + var messageObject = await dp.Target.onceAttachedToTarget(); + workerId = messageObject.params.targetInfo.targetId; + testRunner.log('Worker created'); + + sendCommandToWorker('Debugger.enable', {}); + sendCommandToWorker('Runtime.runIfWaitingForDebugger', {}); + + var pauseCount = 0; + var evalRequestId; + dp.Target.onReceivedMessageFromTarget(async messageObject => { + var message = JSON.parse(messageObject.params.message); + if (message.method === 'Debugger.paused') { + testRunner.log('SUCCESS: Worker paused'); + if (++pauseCount === 1) { + evalRequestId = sendCommandToWorker('Runtime.evaluate', {expression: 'global_value'}); + } else { + testRunner.log('FAIL: debugger paused second time'); + testRunner.completeTest(); + } + } else if (evalRequestId && message.id === evalRequestId) { + var value = message.result.result.value; + if (value === 1) + testRunner.log('SUCCESS: global_value is 1'); + else + testRunner.log('FAIL: setTimeout callback fired while script execution was paused'); + sendCommandToWorker('Debugger.disable', {}); + testRunner.completeTest(); + } + }); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes-expected.txt index ed52d23..55d32b9 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes-expected.txt
@@ -1,3 +1,4 @@ + Paused on 'debugger;' Variable value changed Stacktrace re-read again
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes.html deleted file mode 100644 index 20004b4..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes.html +++ /dev/null
@@ -1,72 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/inspector-protocol-test.js"></script> -<script> - -function TestFunction() -{ - var a = 2; - debugger; - debugger; -} - -function test() -{ - var newVariableValue = 55; - - InspectorTest.sendCommand("Debugger.enable", {}); - - InspectorTest.eventHandler["Debugger.paused"] = handleDebuggerPaused; - - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "setTimeout(TestFunction, 0)" }); - - function handleDebuggerPaused(messageObject) - { - InspectorTest.log("Paused on 'debugger;'"); - InspectorTest.eventHandler["Debugger.paused"] = undefined; - - var topFrame = messageObject.params.callFrames[0]; - var topFrameId = topFrame.callFrameId; - InspectorTest.sendCommand("Debugger.evaluateOnCallFrame", { "callFrameId": topFrameId, "expression": "a = " + newVariableValue }, callbackChangeValue); - } - - function callbackChangeValue(response) - { - InspectorTest.log("Variable value changed"); - InspectorTest.eventHandler["Debugger.paused"] = callbackGetBacktrace; - InspectorTest.sendCommand("Debugger.resume", { }); - } - - function callbackGetBacktrace(response) - { - InspectorTest.log("Stacktrace re-read again"); - var localScope = response.params.callFrames[0].scopeChain[0]; - InspectorTest.sendCommand("Runtime.getProperties", { "objectId": localScope.object.objectId }, callbackGetProperties); - } - - function callbackGetProperties(response) - { - InspectorTest.log("Scope variables downloaded anew"); - var varNamedA; - var propertyList = response.result.result; - for (var i = 0; i < propertyList.length; i++) { - if (propertyList[i].name === "a") { - varNamedA = propertyList[i]; - break; - } - } - if (varNamedA) { - var actualValue = varNamedA.value.value; - InspectorTest.log("New variable is " + actualValue + ", expected is " + newVariableValue + ", old was: 2"); - InspectorTest.log(actualValue == newVariableValue ? "SUCCESS" : "FAIL"); - } else { - InspectorTest.log("Failed to find variable in scope"); - } - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes.js new file mode 100644 index 0000000..09e007d --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/updateCallFrameScopes.js
@@ -0,0 +1,41 @@ +(async function(testRunner) { + let {page, session, dp} = await testRunner.startBlank(''); + + var newVariableValue = 55; + + dp.Debugger.enable(); + dp.Runtime.evaluate({expression: ` + function TestFunction() { + var a = 2; + debugger; + debugger; + } + setTimeout(TestFunction, 0); + `}); + + var messageObject = await dp.Debugger.oncePaused(); + testRunner.log(`Paused on 'debugger;'`); + var topFrame = messageObject.params.callFrames[0]; + var topFrameId = topFrame.callFrameId; + + dp.Debugger.evaluateOnCallFrame({callFrameId: topFrameId, expression: 'a = ' + newVariableValue }); + testRunner.log('Variable value changed'); + dp.Debugger.resume(); + + var response = await dp.Debugger.oncePaused(); + testRunner.log('Stacktrace re-read again'); + var localScope = response.params.callFrames[0].scopeChain[0]; + + response = await dp.Runtime.getProperties({objectId: localScope.object.objectId }); + testRunner.log('Scope variables downloaded anew'); + var propertyList = response.result.result; + var varNamedA = propertyList.find(x => x.name === 'a'); + if (varNamedA) { + var actualValue = varNamedA.value.value; + testRunner.log('New variable is ' + actualValue + ', expected is ' + newVariableValue + ', old was: 2'); + testRunner.log(actualValue == newVariableValue ? 'SUCCESS' : 'FAIL'); + } else { + testRunner.log('Failed to find variable in scope'); + } + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/inspector-protocol-test.js b/third_party/WebKit/LayoutTests/inspector-protocol/resources/inspector-protocol-test.js index ca43106..f2c60bad 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/resources/inspector-protocol-test.js +++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/inspector-protocol-test.js
@@ -312,7 +312,7 @@ var eventName = match[3]; eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1); if (match[1] === 'once') - return () => this._waitForEvent(`${agentName}.${eventName}`); + return eventMatcher => this._waitForEvent(`${agentName}.${eventName}`, eventMatcher); if (match[1] === 'off') return listener => this._removeEventHandler(`${agentName}.${eventName}`, listener); return listener => this._addEventHandler(`${agentName}.${eventName}`, listener); @@ -335,9 +335,11 @@ this._eventHandlers.set(eventName, handlers); } - _waitForEvent(eventName) { + _waitForEvent(eventName, eventMatcher) { return new Promise(callback => { var handler = result => { + if (eventMatcher && !eventMatcher(result)) + return; this._removeEventHandler(eventName, handler); callback(result); };
diff --git a/third_party/WebKit/Source/core/layout/ng/geometry/ng_box_strut.h b/third_party/WebKit/Source/core/layout/ng/geometry/ng_box_strut.h index 5b70b24..6b91aca 100644 --- a/third_party/WebKit/Source/core/layout/ng/geometry/ng_box_strut.h +++ b/third_party/WebKit/Source/core/layout/ng/geometry/ng_box_strut.h
@@ -26,6 +26,13 @@ block_start(block_start), block_end(block_end) {} + LayoutUnit LineLeft(TextDirection direction) const { + return IsLtr(direction) ? inline_start : inline_end; + } + LayoutUnit LineRight(TextDirection direction) const { + return IsLtr(direction) ? inline_end : inline_start; + } + LayoutUnit InlineSum() const { return inline_start + inline_end; } LayoutUnit BlockSum() const { return block_start + block_end; }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.cc index 4a35415f1..250b93f 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.cc
@@ -86,7 +86,8 @@ // Compute box properties regardless of needs_box_fragment since close tag may // also set needs_box_fragment. - box->line_left_position = position + item_result.margins.inline_start; + box->line_left_position = + position + item_result.margins.LineLeft(item.Style()->Direction()); box->borders_paddings_block_start = item_result.borders_paddings_block_start; box->borders_paddings_block_end = item_result.borders_paddings_block_end; return box; @@ -155,7 +156,8 @@ const NGInlineItemResult& item_result, LayoutUnit position) { DCHECK(needs_box_fragment); - line_right_position = position - item_result.margins.inline_end; + line_right_position = + position - item_result.margins.LineRight(item.Style()->Direction()); // We have right edge on close tag, and if the box does not have a // continuation. // TODO(kojii): Needs review when we change SplitInlines().
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc index 01b1c7f..d704839 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -282,6 +282,11 @@ NGTextFragmentBuilder* text_builder) { DCHECK(item_result->layout_result); + // The input |position| is the line-left edge of the margin box. + // Adjust it to the border box by adding the line-left margin. + const ComputedStyle& style = *item.Style(); + position += item_result->margins.LineLeft(style.Direction()); + NGInlineBoxState* box = box_states_.OnOpenTag(item, *item_result, line_box, position); @@ -312,7 +317,7 @@ // TODO(kojii): Try to eliminate the wrapping text fragment and use the // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| // requires a text fragment. - text_builder->SetDirection(item.Style()->Direction()); + text_builder->SetDirection(style.Direction()); text_builder->SetSize({fragment.InlineSize(), block_size}); LayoutUnit line_top = item_result->margins.block_start - metrics.ascent; RefPtr<NGPhysicalTextFragment> text_fragment = text_builder->ToTextFragment(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc index 9857544..771d4b4 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -255,6 +255,22 @@ intrinsic_logical_height -= border_scrollbar_padding.BlockSum(); box_->SetIntrinsicContentLogicalHeight(intrinsic_logical_height); + // LayoutBox::Margin*() should be used value, while we set computed value + // here. This is not entirely correct, but these values are not used for + // layout purpose. + // BaselinePosition() relies on margins set to the box, and computed value is + // good enough for it to work correctly. + // Set this only for atomic inlines, or we end up adding margins twice. + if (box_->IsAtomicInlineLevel()) { + NGBoxStrut margins = + ComputeMargins(constraint_space, Style(), + constraint_space.WritingMode(), Style().Direction()); + box_->SetMarginBefore(margins.block_start); + box_->SetMarginAfter(margins.block_end); + box_->SetMarginStart(margins.inline_start); + box_->SetMarginEnd(margins.inline_end); + } + // TODO(ikilpatrick) is this the right thing to do? if (box_->IsLayoutBlockFlow()) { ToLayoutBlockFlow(box_)->RemoveFloatingObjects();
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index df9d421..f213a33 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -20410,6 +20410,32 @@ <int value="1" label="identical"/> </enum> +<enum name="InstantTethering_ConnectionToHostResult_Failure"> + <int value="0" label="Unknown error"/> + <int value="1" label="Tethering timed out"/> + <int value="2" label="Client connection error"/> +</enum> + +<enum name="InstantTethering_ConnectionToHostResult_Failure_ClientConnection"> + <int value="0" label="Timeout while waiting to connect"/> + <int value="1" label="Canceled by a new connection attempt"/> +</enum> + +<enum name="InstantTethering_ConnectionToHostResult_Failure_TetheringTimeout"> + <int value="0" label="First-time setup was required"/> + <int value="1" label="First-time setup was not required"/> +</enum> + +<enum name="InstantTethering_ConnectionToHostResult_ProvisioningFailureRate"> + <int value="0" label="Provisioning failed"/> + <int value="1" label="Other"/> +</enum> + +<enum name="InstantTethering_ConnectionToHostResult_SuccessRate"> + <int value="0" label="Success"/> + <int value="1" label="Failure"/> +</enum> + <enum name="IntelMaxMicroArchitecture"> <int value="0" label="Pentium"/> <int value="1" label="SSE"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 18ce1dad..d304889b 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -26619,6 +26619,96 @@ </summary> </histogram> +<histogram name="InstantTethering.ConnectionToHostResult.Failure" + enum="InstantTethering_ConnectionToHostResult_Failure"> + <owner>hansberry@chromium.com</owner> + <summary> + Provides a top-level breakdown of the times a connection to a host has + failed. + + An "unknown error" is generally caused by the host returning an + "unknown error" response code. Tethering timing out and client + connection error and 3) are both broken down further in + InstantTethering.ConnectionToHostResult.Failure.TetheringTimeout and + InstantTethering.ConnectionToHostResult.Failure.ClientConnection, + respectively. + </summary> +</histogram> + +<histogram + name="InstantTethering.ConnectionToHostResult.Failure.ClientConnection" + enum="InstantTethering_ConnectionToHostResult_Failure_ClientConnection"> + <owner>hansberry@chromium.com</owner> + <summary> + Breaks down the reasons why the client failed to connect to the hotspot, and + the number of times they occurred. This histogram captures 2 reasons: 1) the + connection attempt to the hotspot timed out, or 2) any stage of the + connection attempt was canceled by a new connection attempt. + + This histogram breaks down the "client connection error" count of + InstantTethering.ConnectionToHostResult.Failure. + </summary> +</histogram> + +<histogram + name="InstantTethering.ConnectionToHostResult.Failure.TetheringTimeout" + enum="InstantTethering_ConnectionToHostResult_Failure_TetheringTimeout"> + <owner>hansberry@chromium.com</owner> + <summary> + Captures the number of times of whether or not first-time setup was required + when tethering timed out. + + Starting tethering on the host works like so: if first-time setup is + required on the host, a first-time setup UI is shown on the host; once the + user interacts with it, the provisioning app is called. If first-time setup + is not required, then the provisioning app is directly called. To be clear: + the provisioning app is always run. + + There are two possible ways for tethering to time out: either the + provisioning app flaked (crashed or hung, and never called back to Instant + Tethering), or the user never interacted with the first-time setup UI flow + (assuming first-time setup was required). + + Because it's very unlikely for the provisioning app to flake, we can read + the "was first-time setup" count as almost always indicative of + the user not interacting with the first-time setup UI. We expect the + "was not first-time setup" count to be low (because, as mentioned, + it's very unlikely for the provisioning app to flake). + + This histogram breaks down the "tethering timed out" count of + InstantTethering.ConnectionToHostResult.Failure. + </summary> +</histogram> + +<histogram + name="InstantTethering.ConnectionToHostResult.ProvisioningFailureRate" + enum="InstantTethering_ConnectionToHostResult_ProvisioningFailureRate"> + <owner>hansberry@chromium.org</owner> + <summary> + Provides a breakdown of the times a connection to a host was either + unsuccessful due to provisioning failure (the carrier disallows tethering) + or "other" (this is captured under + InstantTethering.ConnectionToHostResult.SuccessRate). + + This metric captures the rough percentage of connections which are + unsuccessful due to provisioning failure. It is separate from + InstantTethering.ConnectionToHostResult.SuccessRate and the metrics related + to it because provisioning failure is neither truly a success nor an error. + </summary> +</histogram> + +<histogram name="InstantTethering.ConnectionToHostResult.SuccessRate" + enum="InstantTethering_ConnectionToHostResult_SuccessRate"> + <owner>hansberry@chromium.com</owner> + <summary> + Captures the count of successful and failed connection attempts. + + This metric provides an immediate understanding of the Instant Tethering + connection success rate. The counts of failure are broken down in + InstantTethering.ConnectionToHostResult.Failure. + </summary> +</histogram> + <histogram name="InterProcessTimeTicks.BrowserAhead" units="ms"> <owner>ppi@chromium.org</owner> <summary> @@ -87566,6 +87656,14 @@ </summary> </histogram> +<histogram name="WinJumplist.NotificationTimeInterval" units="ms"> + <owner>chengx@chromium.org</owner> + <summary> + The time interval between two adjacent update notifications if it's less + than 3500 ms. + </summary> +</histogram> + <histogram name="WinJumplist.OnFaviconDataAvailableDuration" units="ms"> <obsolete> Obsolete 06/22/2017 as it's no longer needed. @@ -96576,6 +96674,7 @@ <suffix name="OfflinePageMetadata" label="OfflinePageMetadata"/> <suffix name="Passwords" label="Passwords"/> <suffix name="Precache" label="Precache"/> + <suffix name="PrefetchStore" label="PrefetchStore"/> <suffix name="Predictor" label="Predictor"/> <suffix name="PreviewsOptOut" label="PreviewsOptOut"/> <suffix name="Quota" label="Quota"/>
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index 2b09d34d..2eb4dba0 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -311,9 +311,6 @@ // NSAccessibility informal protocol implementation. - (BOOL)accessibilityIsIgnored { - if (!node_) - return YES; - return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole] || node_->GetData().HasState(ui::AX_STATE_INVISIBLE); } @@ -333,13 +330,10 @@ } - (id)accessibilityFocusedUIElement { - return node_ ? node_->GetDelegate()->GetFocus() : nil; + return node_->GetDelegate()->GetFocus(); } - (NSArray*)accessibilityActionNames { - if (!node_) - return @[]; - base::scoped_nsobject<NSMutableArray> axActions( [[NSMutableArray alloc] init]); @@ -361,11 +355,7 @@ } - (void)accessibilityPerformAction:(NSString*)action { - // Actions are performed asynchronously, so it's always possible for an object - // to change its mind after previously reporting an action as available. - if (![[self accessibilityActionNames] containsObject:action]) - return; - + DCHECK([[self accessibilityActionNames] containsObject:action]); ui::AXActionData data; if ([action isEqualToString:NSAccessibilityShowMenuAction] && AlsoUseShowMenuActionForDefaultAction(node_->GetData())) { @@ -388,9 +378,6 @@ } - (NSArray*)accessibilityAttributeNames { - if (!node_) - return @[]; - // These attributes are required on all accessibility objects. NSArray* const kAllRoleAttributes = @[ NSAccessibilityChildrenAttribute, @@ -460,7 +447,7 @@ - (NSArray*)accessibilityParameterizedAttributeNames { if (!node_) - return @[]; + return nil; static NSArray* const kSelectableTextAttributes = [@[ NSAccessibilityLineForIndexParameterizedAttribute, @@ -485,9 +472,6 @@ } - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName { - if (!node_) - return NO; - if (node_->GetData().HasState(ui::AX_STATE_DISABLED)) return NO; @@ -525,9 +509,6 @@ } - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { - if (!node_) - return; - ui::AXActionData data; // Check for attributes first. Only the |data.action| should be set here - any @@ -566,9 +547,6 @@ } - (id)accessibilityAttributeValue:(NSString*)attribute { - if (!node_) - return nil; // Return nil when detached. Even for AXRole. - SEL selector = NSSelectorFromString(attribute); if ([self respondsToSelector:selector]) return [self performSelector:selector]; @@ -577,9 +555,6 @@ - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter { - if (!node_) - return nil; - SEL selector = NSSelectorFromString([attribute stringByAppendingString:@":"]); if ([self respondsToSelector:selector]) return [self performSelector:selector withObject:parameter]; @@ -592,7 +567,6 @@ - (NSString*)AXRole { if (!node_) return nil; - return [[self class] nativeRoleFromAXRole:node_->GetData().role]; } @@ -660,8 +634,7 @@ - (NSArray*)AXChildren { if (!node_) - return @[]; - + return nil; int count = node_->GetChildCount(); NSMutableArray* children = [NSMutableArray arrayWithCapacity:count]; for (int i = 0; i < count; ++i)
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn index 979cde4..5ff7cec 100644 --- a/ui/app_list/BUILD.gn +++ b/ui/app_list/BUILD.gn
@@ -76,6 +76,7 @@ "//base/third_party/dynamic_annotations", "//components/keyed_service/core", "//components/sync", + "//components/wallpaper", "//skia", "//third_party/icu", "//ui/accessibility",
diff --git a/ui/app_list/search_box_model.cc b/ui/app_list/search_box_model.cc index 877d677..790d9fab 100644 --- a/ui/app_list/search_box_model.cc +++ b/ui/app_list/search_box_model.cc
@@ -81,6 +81,16 @@ observer.Update(); } +void SearchBoxModel::SetWallpaperProminentColors( + const std::vector<SkColor>& colors) { + if (wallpaper_prominent_colors_ == colors) + return; + + wallpaper_prominent_colors_ = colors; + for (auto& observer : observers_) + observer.WallpaperProminentColorsChanged(); +} + void SearchBoxModel::AddObserver(SearchBoxModelObserver* observer) { observers_.AddObserver(observer); }
diff --git a/ui/app_list/search_box_model.h b/ui/app_list/search_box_model.h index fe53744..36b27781 100644 --- a/ui/app_list/search_box_model.h +++ b/ui/app_list/search_box_model.h
@@ -74,6 +74,12 @@ const base::string16& text() const { return text_; } bool is_voice_query() const { return is_voice_query_; } + // Sets/gets the wallpaper prominent colors. + void SetWallpaperProminentColors(const std::vector<SkColor>& colors); + const std::vector<SkColor>& wallpaper_prominent_colors() const { + return wallpaper_prominent_colors_; + } + void AddObserver(SearchBoxModelObserver* observer); void RemoveObserver(SearchBoxModelObserver* observer); @@ -84,6 +90,7 @@ gfx::SelectionModel selection_model_; base::string16 text_; bool is_voice_query_ = false; + std::vector<SkColor> wallpaper_prominent_colors_; base::ObserverList<SearchBoxModelObserver> observers_;
diff --git a/ui/app_list/search_box_model_observer.h b/ui/app_list/search_box_model_observer.h index 9dfd2e8..090f87a 100644 --- a/ui/app_list/search_box_model_observer.h +++ b/ui/app_list/search_box_model_observer.h
@@ -24,6 +24,9 @@ // Invoked when text or voice search flag is changed. virtual void Update() = 0; + // Invoked when wallpaper prominent colors are changed. + virtual void WallpaperProminentColorsChanged() = 0; + protected: virtual ~SearchBoxModelObserver() {} };
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index 48a22b3..45f30f1 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" +#include "components/wallpaper/wallpaper_color_profile.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_model.h" @@ -26,6 +27,7 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/events/event.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/shadow_value.h" @@ -40,6 +42,8 @@ #include "ui/views/shadow_border.h" #include "ui/views/widget/widget.h" +using wallpaper::ColorProfileType; + namespace app_list { namespace { @@ -62,14 +66,17 @@ constexpr SkColor kDefaultSearchboxColor = SkColorSetARGBMacro(0xDE, 0x00, 0x00, 0x00); +constexpr int kLightVibrantBlendAlpha = 0xB3; + // A background that paints a solid white rounded rect with a thin grey border. class SearchBoxBackground : public views::Background { public: - SearchBoxBackground() + explicit SearchBoxBackground(SkColor color) : background_border_corner_radius_( features::IsFullscreenAppListEnabled() ? kBackgroundBorderCornerRadiusFullscreen - : kBackgroundBorderCornerRadius) {} + : kBackgroundBorderCornerRadius), + color_(color) {} ~SearchBoxBackground() override {} private: @@ -79,11 +86,12 @@ cc::PaintFlags flags; flags.setAntiAlias(true); - flags.setColor(kSearchBoxBackgroundDefault); + flags.setColor(color_); canvas->DrawRoundRect(bounds, background_border_corner_radius_, flags); } const int background_border_corner_radius_; + const SkColor color_; DISALLOW_COPY_AND_ASSIGN(SearchBoxBackground); }; @@ -156,7 +164,8 @@ AddChildView(content_container_); SetShadow(GetShadowForZHeight(2)); - content_container_->SetBackground(base::MakeUnique<SearchBoxBackground>()); + content_container_->SetBackground( + base::MakeUnique<SearchBoxBackground>(kSearchBoxBackgroundDefault)); views::BoxLayout* layout = new views::BoxLayout( views::BoxLayout::kHorizontal, gfx::Insets(0, kPadding), @@ -216,6 +225,7 @@ model_->search_box()->AddObserver(this); SpeechRecognitionButtonPropChanged(); HintTextChanged(); + WallpaperProminentColorsChanged(); } bool SearchBoxView::HasSearch() const { @@ -498,6 +508,46 @@ NotifyQueryChanged(); } +void SearchBoxView::WallpaperProminentColorsChanged() { + if (!is_fullscreen_app_list_enabled_) + return; + + const std::vector<SkColor> prominent_colors = + model_->search_box()->wallpaper_prominent_colors(); + if (prominent_colors.empty()) + return; + + DCHECK_EQ(static_cast<size_t>(ColorProfileType::NUM_OF_COLOR_PROFILES), + prominent_colors.size()); + const SkColor dark_muted = + prominent_colors[static_cast<int>(ColorProfileType::DARK_MUTED)]; + const bool dark_muted_available = SK_ColorTRANSPARENT != dark_muted; + google_icon_->SetImage(gfx::CreateVectorIcon( + kIcGoogleBlackIcon, kGoogleIconSize, + dark_muted_available ? dark_muted : kDefaultSearchboxColor)); + speech_button_->SetImage( + views::Button::STATE_NORMAL, + gfx::CreateVectorIcon( + kIcMicBlackIcon, kMicIconSize, + dark_muted_available ? dark_muted : kDefaultSearchboxColor)); + search_box_->set_placeholder_text_color( + dark_muted_available ? dark_muted : kDefaultSearchboxColor); + + const SkColor light_vibrant = + prominent_colors[static_cast<int>(ColorProfileType::LIGHT_VIBRANT)]; + const SkColor light_vibrant_mixed = color_utils::AlphaBlend( + SK_ColorWHITE, light_vibrant, kLightVibrantBlendAlpha); + const bool light_vibrant_available = SK_ColorTRANSPARENT != light_vibrant; + content_container_->SetBackground(base::MakeUnique<SearchBoxBackground>( + light_vibrant_available ? light_vibrant_mixed + : kSearchBoxBackgroundDefault)); + search_box_->SetBackgroundColor(light_vibrant_available + ? light_vibrant_mixed + : kSearchBoxBackgroundDefault); + + SchedulePaint(); +} + void SearchBoxView::OnSpeechRecognitionStateChanged( SpeechRecognitionState new_state) { SpeechRecognitionButtonPropChanged();
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h index d2cee93..a8e8486 100644 --- a/ui/app_list/views/search_box_view.h +++ b/ui/app_list/views/search_box_view.h
@@ -110,6 +110,7 @@ void HintTextChanged() override; void SelectionModelChanged() override; void Update() override; + void WallpaperProminentColorsChanged() override; // Overridden from SpeechUIModelObserver: void OnSpeechRecognitionStateChanged(
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 710731ee..4441ecb 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/compiler/compiler.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build/config/ui.gni") +import("//build/util/branding.gni") import("//testing/test.gni") import("//ui/base/ui_features.gni") import("//ui/ozone/ozone.gni") @@ -1014,6 +1015,7 @@ "//ui/resources:ui_test_pak_bundle_data", ] info_plist = "test/framework-Info.plist" + extra_substitutions = [ "CHROMIUM_BUNDLE_ID=$chrome_mac_bundle_id" ] output_name = "ui_unittests Framework" } }
diff --git a/ui/base/test/framework-Info.plist b/ui/base/test/framework-Info.plist index f3b7fc725b..3d749a5 100644 --- a/ui/base/test/framework-Info.plist +++ b/ui/base/test/framework-Info.plist
@@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> - <string>${CHROMIUM_BUNDLE_ID}.framework</string> + <string>${CHROMIUM_BUNDLE_ID}.ui_unittests.framework</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key>
diff --git a/ui/views/widget/native_widget_mac_accessibility_unittest.mm b/ui/views/widget/native_widget_mac_accessibility_unittest.mm index 7988061f..d195839 100644 --- a/ui/views/widget/native_widget_mac_accessibility_unittest.mm +++ b/ui/views/widget/native_widget_mac_accessibility_unittest.mm
@@ -140,86 +140,6 @@ } // namespace -// Test that all methods in the NSAccessibility informal protocol can be called -// on a retained accessibility object after the source view is deleted. -TEST_F(NativeWidgetMacAccessibilityTest, Lifetime) { - Textfield* view = AddChildTextfield(widget()->GetContentsView()->size()); - base::scoped_nsobject<NSObject> ax_node(view->GetNativeViewAccessible(), - base::scoped_policy::RETAIN); - - NSString* kAttribute = NSAccessibilityValueAttribute; - NSString* kParamAttribute = - NSAccessibilityStringForRangeParameterizedAttribute; - NSString* kAction = NSAccessibilityShowMenuAction; - - EXPECT_TRUE( - [[ax_node accessibilityAttributeNames] containsObject:kAttribute]); - EXPECT_NSEQ(kTestStringValue, - [ax_node accessibilityAttributeValue:kAttribute]); - EXPECT_TRUE([ax_node accessibilityIsAttributeSettable:kAttribute]); - EXPECT_TRUE([[ax_node accessibilityActionNames] containsObject:kAction]); - EXPECT_FALSE([ax_node accessibilityIsIgnored]); - - // Not implemented, but be sure to update this test if it ever is. - EXPECT_FALSE( - [ax_node respondsToSelector:@selector(accessibilityActionDescription:)]); - - EXPECT_TRUE([[ax_node accessibilityParameterizedAttributeNames] - containsObject:kParamAttribute]); - NSValue* range = [NSValue valueWithRange:NSMakeRange(0, kTestStringLength)]; - EXPECT_NSEQ( - kTestStringValue, - [ax_node accessibilityAttributeValue:kParamAttribute forParameter:range]); - - // The following is also "not implemented", but the informal protocol category - // provides a default implementation. - EXPECT_EQ(NSNotFound, [ax_node accessibilityIndexOfChild:nil]); - - // The only usually available array attribute is AXChildren, so go up a level - // to the Widget to test that a bit. The default implementation just gets the - // attribute normally and returns its size (if it's an array). - NSString* kChildren = NSAccessibilityChildrenAttribute; - base::scoped_nsobject<NSObject> ax_parent( - [ax_node accessibilityAttributeValue:NSAccessibilityParentAttribute], - base::scoped_policy::RETAIN); - EXPECT_EQ(1u, [ax_parent accessibilityArrayAttributeCount:kChildren]); - EXPECT_EQ( - ax_node.get(), - [ax_parent accessibilityArrayAttributeValues:kChildren index:0 - maxCount:1][0]); - - // If it is not an array, the default implementation throws an exception, so - // it's impossible to test these methods further on |ax_node|, apart from the - // following, before deleting the view. - EXPECT_EQ(0u, [ax_node accessibilityArrayAttributeCount:kChildren]); - - delete view; - - EXPECT_TRUE( - [ax_node respondsToSelector:@selector(accessibilityAttributeNames)]); - EXPECT_EQ(@[], [ax_node accessibilityAttributeNames]); - EXPECT_EQ(nil, [ax_node accessibilityAttributeValue:kAttribute]); - EXPECT_FALSE([ax_node accessibilityIsAttributeSettable:kAttribute]); - [ax_node accessibilitySetValue:kTestStringValue forAttribute:kAttribute]; - - EXPECT_EQ(@[], [ax_node accessibilityActionNames]); - [ax_node accessibilityPerformAction:kAction]; - - EXPECT_TRUE([ax_node accessibilityIsIgnored]); - EXPECT_EQ(nil, [ax_node accessibilityHitTest:NSZeroPoint]); - EXPECT_EQ(nil, [ax_node accessibilityFocusedUIElement]); - - EXPECT_EQ(@[], [ax_node accessibilityParameterizedAttributeNames]); - EXPECT_NSEQ(nil, [ax_node accessibilityAttributeValue:kParamAttribute - forParameter:range]); - - // Test the attributes with default implementations provided. - EXPECT_EQ(NSNotFound, [ax_node accessibilityIndexOfChild:nil]); - - // The Widget is currently still around, but the child should be gone. - EXPECT_EQ(0u, [ax_parent accessibilityArrayAttributeCount:kChildren]); -} - // Check that potentially keyboard-focusable elements are always leaf nodes. TEST_F(NativeWidgetMacAccessibilityTest, FocusableElementsAreLeafNodes) { // LabelButtons will have a label inside the button. The label should be